用SpringMVC源码解析之配置加载SpringServletContainerInitializer
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
@Override
public void onStartup ( Set < Class < ? > > webAppInitializerClasses , ServletContext servletContext )
throws ServletException {
List < WebApplicationInitializer > initializers = new LinkedList < WebApplicationInitializer > ( ) ;
if ( webAppInitializerClasses ! = null ) {
for ( Class < ? > waiClass : webAppInitializerClasses ) {
/ / Be defensive : Some servlet containers provide us with invalid classes ,
/ / no matter what @HandlesTypes says...
if ( !waiClass.isInterface ( ) & & !Modifier.isAbstract ( waiClass.getModifiers ( ) ) & &
WebApplicationInitializer. class .isAssignableFrom ( waiClass ) ) {
try {
initializers. add ( ( WebApplicationInitializer ) waiClass.newInstance ( ) ) ;
}
catch(Throwable ex) {
throw new ServletException(“无法实例化WebApplicationInitializer类”,ex);
}
}
}
}
如果(initializers.isEmpty()) {
servletContext. log ( “检测到的无弹簧WebApplicationInitializer类型上的类路径”);
返回;
}
servletContext. log (initializers.size() + “类路径上检测到的弹簧WebApplicationInitializers”);
AnnotationAwareOrderComparator.sort(初始化);
for (WebApplicationInitializer initializer:initializers) {
initializer.onStartup(servletContext);
}
/ [mw_shl_code]
[color = #000][font=sans-serif][size=16px]进入到DispatcherServlet初始化器org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这个方法[/size][/font][/color]
[mw_shl_code = applescript , true ] @Override
public void onStartup ( ServletContext servletContext ) throws ServletException {
/ / 调用上下文加载器初始化类的onStartup方法
super.onStartup ( servletContext ) ;
/ / 注册DispatcherServlet
registerDispatcherServlet ( servletContext ) ;
}
|
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#onStartup,执行ContextLoader初始化器
1
2
3
4
|
@Override
public void onStartup ( ServletContext servletContext ) throws ServletException {
registerContextLoaderListener ( servletContext ) ;
}
|
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#registerContextLoaderListener,注册ContextLoader监听器
[mw_shl_code = applescript,true] protected void registerContextLoaderListener(ServletContext servletContext){
//获取上层应用上下文对象 - >
WebApplicationContext rootAppContext = createRootApplicationContext();
if(rootAppContext!= null){
//创建上下文加载监听器
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
//把上下文加载监听器加载到servlet容器
servletContext.addListener(listener);
}
else {
logger.debug(“没有注册ContextLoaderListener,因为”+
“createRootApplicationContext()没有返回应用程序上下文”);
}
} [/ mw_shl_code]
进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createRootApplicationContext
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Override
protected WebApplicationContext createRootApplicationContext ( ) {
/ / 从子类实现中或者从@Configuration、@Component注解配置中获取配置类
Class < ? > [] configClasses = getRootConfigClasses ( ) ;
if ( !ObjectUtils.isEmpty ( configClasses ) ) {
/ / 如果没有配置就默认初始化基于注解的web应用上下文类
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext ( ) ;
rootAppContext. register ( configClasses ) ;
return rootAppContext;
}
else {
return null;
}
}
|
进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#getRootApplicationContextInitializers
1
2
3
|
protected ApplicationContextInitializer < ? > [] getRootApplicationContextInitializers ( ) {
return null;
}
|
返回到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这一行
1
2
|
/ / 注册DispatcherServlet
registerDispatcherServlet ( servletContext ) ;
|
进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerDispatcherServlet
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
protected void registerDispatcherServlet ( ServletContext servletContext ) {
/ / 获取servletName,默认名称是dispatcher
String servletName = getServletName();
Assert.hasLength(servletName,“getServletName()不能返回空或null”);
/ / 创建servlet程序上下文 - >
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext,
“createServletApplicationContext()没有返回
servlet [” + servletName + “]”)的应用程序“ + ”上下文;
/ / 创建DispatcherServlet
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
/ / 注册的servlet上下文初始化器,这里是模板实现
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
/ / 添加的DispatcherServlet到的servlet容器
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName,dispatcherServlet);
Assert.notNull(注册,
“无法注册名称为'的servlet + ” + servletName + “'。” +
“检查是否有另一个以相同名称注册的servlet。”);
registration.setLoadOnStartup( 1 );
/ / 获取servletMapping实现,这里是抽象实现,注册映射
registration.addMapping(getServletMappings());
/ / 设置是否支持异步,默认支持
registration.setAsyncSupported(isAsyncSupported());
/ / 获取servletFilter,这里是模板实现
Filter [] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter:filters) {
/ / 注册过滤器 - >
registerServletFilter(servletContext,filter);
/ / 定制化注册,默认是模板实现
customizeRegistration ( registration ) ;
}
|
进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createServletApplicationContext
01
02
03
04
05
06
07
08
09
10
11
12
|
@Override
protected WebApplicationContext createServletApplicationContext ( ) {
/ / 创建基于注解的web应用上下文
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext ( ) ;
/ / 从子类实现中或者从@Configuration、@Component注解配置中获取配置类
Class < ? > [] configClasses = getServletConfigClasses ( ) ;
if ( !ObjectUtils.isEmpty ( configClasses ) ) {
/ / 注册@Configuration配置的配置加载类到AnnotationConfigWebApplicationContext
servletAppContext. register ( configClasses ) ;
}
return servletAppContext;
}
|
进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerServletFilter
[mw_shl_code=applescript,true]protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
//获取filteName
String filterName = Conventions.getVariableName(filter);
//添加filter到servlet容器
Dynamic registration = servletContext.addFilter(filterName, filter);
//如果filter注册失败
if (registration == null) {
int counter = -1;
while (counter == -1 || registration == null) {
counter++;
//添加filter#0 到servlet容器
registration = servletContext.addFilter(filterName + "#" + counter, filter);
//提示有同样的名字的过滤器已注册过
Assert.isTrue(计数器<100,
“无法注册过滤器'”+过滤器+“'。”+
“可能已经注册了相同的过滤器实例吗?”);
}
}
//是否支持异步,默认是
registration.setAsyncSupported(isAsyncSupported());
registration.addMappingForServletNames(getDispatcherTypes(),false,getServletName());
退货登记;
} [/ mw_shl_code]
原文 - 微信公众号:天河聊架构