赞
踩
利用 SpringBoot 自动配置机制,SpringBoot 会导入一个类型为 ServletWebServerFactoryAutoConfiguration 的配置类
ServletWebServerFactoryAutoConfigurations 类上存在 @Import 注解,@Import 注解有以下几个特性:
ServletWebServerFactoryAutoConfiguration 类属于第三种情况,我们继续分析
spring-boot-starter-web 默认包含依赖 spring-boot-starter-tomcat,因此 Spring 中存在类型为 EmbeddedTomcat 的配置类,EmbeddedJetty、EmbeddedUndertow 因为不满足 @ConditionalOnClass 注解的条件,所以默认情况下 web 容器是 Tomcat
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <version>2.6.13</version>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-jetty</artifactId>
- <version>2.6.13</version>
- </dependency>

此时项目是以 Jetty 为 Web 容器
AbstractApplicationContext 的 refresh 方法是一个空壳方法,我们主要看它的实现类 ServletWebServerApplicationContext
其中 getSelfInitializer 方法的返回类型是 ServletContextInitializer, ServletContextInitializer 是一个函数式接口
所以上述代码等价于下列形式:
- private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
- return new ServletContextInitializer() {
- @Override
- public void onStartup(ServletContext servletContext) throws ServletException {
- prepareWebApplicationContext(servletContext);
- registerApplicationScope(servletContext);
- WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
- for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
- beans.onStartup(servletContext);
- }
- }
- };
- }
经过一系列的方法调用,最终会调用 StandardContext 的 startInternal 方法
其中 ServletWebServerApplicationContext$lambda 就是我们上文分析的 getSelfInitializer 方法
ServletContextInitializer 的 onStartup 方法,会向容器中注册 Servlet、Filter,DispatcherServlet 就是在这个阶段注册进去的
我们在上文中已经分析过了,默认情况下 Spring 中存在的与 web 容器相关的配置类是 EmbeddedTomcat ,该配置类会定义一个类型为 TomcatServletWebServerFactory 的 bean
通过 TomcatServletWebServerFactory 的类图,我们可以知道它是 ErrorPageRegistry 的子类
其中 getRegistrars 方法会查找 Spring 中类型为 ErrorPageRegistrar 的 bean,在自动配置类 ErrorMvcAutoConfiguration 中就定义了一个类型为 ErrorPageCustomizer 的 bean,该 bean 是 ErrorPageRegistrar 的子类
errorPageCustomizer 方法会有一个类型为 DispatcherServletPath,根据 Spring 的机制,它会从Spring 中先查找类型为 DispatcherServletPath 的 bean,如果该 bean 还没有被实例化,则优先实例化 bean,作用类似于 @DependsOn
我们再追踪 DispatcherServletPath 的实例化过程,DispatcherServletPath 是一个函数式接口,它有一个实现类 DispatcherServletRegistrationBean
DispatcherServletAutoConfiguration 的内部类 DispatcherServletRegistrationConfiguration 定义了一个返回类型为 DispatcherServletRegistrationBean 的 bean。这个方法有一个类型为 DispatcherServlet 的参数,和 DispatcherServletPath 的特性一致,它会优先实例化类型为 DispatcherServlet 的 bean
此时 Spring 中就有一个类型为 DispatcherServlet 的 bean
如果 DispatcherServlet 还没有执行 onRefresh 方法,第一次发送请求,就会执行 onRefresh 方法
至此 DispatcherServlet 的实例化以及组件初始化已经完成
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。