本文主要内容:
1. SpringMVC核心类DispatcherServlet自动装配原理;
2. Spring Boot中如何实现将DispatcherServlet注册到ServletContext中
1. SpringMVC核心类DispatcherServlet自动装配原理
在spring-boot-autoconfigure下的META-INF/spring.factories中key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration
配置的自动装配类信息包含org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
DispatcherServletAutoConfiguration配置类内部类DispatcherServletConfiguration注册了DispatcherServlet; 内部类DispatcherServletRegistrationConfiguration注册了DispatcherServletRegistrationBean
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) // 需要在加载完 ServletWebServerFactoryAutoConfiguration(Tomcat的自动配置类) 后,才会对当前类进行加载 public class DispatcherServletAutoConfiguration {
@Configuration(proxyBeanMethods = false) @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class }) protected static class DispatcherServletConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails()); return dispatcherServlet; } ................... } @Configuration(proxyBeanMethods = false) @Conditional(DispatcherServletRegistrationCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) @Import(DispatcherServletConfiguration.class) protected static class DispatcherServletRegistrationConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) // DispatcherServletRegistrationBean bean需要用到DispatcherServlet的bean对象 // DispatcherServletRegistrationBean 是DispatcherServlet的注册类,赋值将DispatcherServlet注册到ServletContext中 public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath()); registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup()); multipartConfig.ifAvailable(registration::setMultipartConfig); return registration; } }
在SpringBoot启动过程中,会自动配置 DispatcherServlet及DispatcherServletRegistrationBean(DispatcherServlet的注册Bean)
2. Spring Boot中如何实现将DispatcherServlet注册到ServletContext中
DispatcherServletRegistrationBean类图如下
在Spring Boot 启动过程中,刷新上下文(refreshContext)时 会通过上下文对象ConfigurableApplicationContext调用Spring的核心方法refresh;
在AbstractApplicationContext.fresh中通过
A.invokeBeanFactoryPostProcessors(beanFactory)方法会加载在META-INF下spring.facories下key为 EnableAutoConfiguration全限定类名的值,并将类信息存入IOC容器;
B.onRefresh()方法调用TomcatServletWebServerFactory 的 getWebServer方法,创建及启动一个Tomcat后获取ServletContextInitializer时, 会获取到DispatcherServletRegistrationBean对象,传入ApplicationContext对象调用onStartup,(DispatcherServletRegistrationBean中无onStartup方法)最终调用其父类中的onStartup方法,在ServletRegistrationBean中的 addRegistration()方法调用了servletContext.addServlet(name, this.servlet);实现将servlet实例注册到tomcat的servletContext中(等同于在web.xml中配置servlet)