知识储备:基于SpringBoot 2.0.5解析Servlet容器自动配置及容器启动原理

1.Servlet容器自动配置原理

1.知道SpringBoot自动配置原理的都知道(有不了解的可以查看https://blog.csdn.net/qq_36625757/article/details/83929287这篇博客),SpringBoot在启应用动时都会加载各个jar包下的META-INF/spring.factories文件,读取其中的org.springframework.boot.autoconfigure.EnableAutoConfiguration类型的所有自动配置类,从而达到自动配置的效果。而我们的servlet容器的自动配置也是从这个配置文件着手

2.在spring-boot-autoconfigure-2.0.5.RELEASE.jar下的spring.factories文件中,有一个自动配置类org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration是用于自动配置Servlet容器的

我们进入到这个类中

发现,在这个类的头上添加很多注解,通过@ConditionalOnWebApplication(type = Type.SERVLET)注解判断当前项目是否是web项目,如果过不是,这这个配置类就不会生效,通过@EnableConfigurationProperties(ServerProperties.class)注解,向容器中添加ServerProperties组件,在SpringBoot中xxxProperties类都是和配置文件映射的类,用户可以通过配置文件配置类中属性。例如:用户可以通过server.port配置容器端口号。

通过@Import()向容器中批量添加组件,可以发现注解中添加了ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrarServletWebServerFactoryConfiguration.EmbeddedTomcatServletWebServerFactoryConfiguration.EmbeddedJettyServletWebServerFactoryConfiguration.EmbeddedUndertow四个组件。首先我们来到ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar中

发现向容器中添加的是BeanPostProcessorsRegistrar组件,这个组件也是向容器中添加组件,这里是添加WebServerFactoryCustomizerBeanPostProcessor,对于xxxBeanPostProcessor来说,都是bean的后置处理器,即在bean创建完成后,在其初始化前后进行拦截处理(不熟悉后置处理器的可查看https://blog.csdn.net/qq_36625757/article/details/83616097这篇博客)。接下来我们看看通过ServletWebServerFactoryConfiguration.EmbeddedTomcat向容器中导入了啥组件?进入其中

可以发现这个类中有三个内部类,而这三个内部类也是配置类,分别通过@ConditionalOnClass@ConditionalOnMissingBean限制配置类是否生效,由此可见,要想切换servlet容器,只需要添加相应容器的依赖,排除其他容器依赖即可,我们这里一tomcat容器为例介绍,所以我们就看第一个配置类,第一个配置类又通过@Bean向容器中添加了TomcatServletWebServerFactory组件,通过类名大致可以知道这是TomcatServletWebServer容器工厂,进入其中

发现有一个getWebServer()方法获得TomcatWebServer,起初先创建一个tomcat,在设置一些配置,在通过getTomcatWebServer(tomcat)获得TomcatWebServer,进入到getTomcatWebServer(tomcat)中

发现其中是在启动tomcat

3.自动配置,看到这里依旧没有说Servlet是如何自动配置的。前面我们看到ServletWebServerFactoryAutoConfiguration中通过@Bean向容器中添加了一个ServletWebServerFactoryCustomizer组件,接下来我们就进入其中看看

发现实现的接口中有传一个泛型为ConfigurableServletWebServerFactory组件,而TomcatServletWebServerFactory也是这个类型,所以下面就通过customize(ConfigurableServletWebServerFactory factory)方法通过serverProperties对TomcatServletWebServerFactory进行配置,而在TomcatServletWebServerFactory中又在getWebServer()方法中对toncat进行配置,那么org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer.customize(ConfigurableServletWebServerFactory)这个方法又是啥时候调用的呢?

4.前面我们说过ServletWebServerFactoryAutoConfiguration配置类想容器中通过@Import注解注册BeanPostProcessorsRegistrar,而BeanPostProcessorsRegistrar又想容器中注册一个WebServerFactoryCustomizerBeanPostProcessor后置处理器,下我们就进入其中看看

发现在bean初始化之前先判断当前要创建的bean是否是WebServerFactory类型的,如果是就调用postProcessBeforeInitialization((WebServerFactory) bean);方法,进入方法中

发现,通过beanFactory获得所有类型为WebServerFactoryCustomizer的组件,并且调用他们的customize()方法,而ServletWebServerFactoryCustomizer就是WebServerFactoryCustomizer类型的,所以他的customize()方法也就会被调用了,Tomcat也就会进行自动配置了。

2.Servlet容器启动流程

1.首先容器通过程序主入口SpringApplication.run(SpringbootMybatisApplication.class, args);启动

通过createApplicationContext();获得环境对象,进入其中

发现再通过当前应用类型获得不同的环境,web应用创建AnnotationConfigServletWebServerApplicationContext,响应式web应用创建AnnotationConfigReactiveWebServerApplicationContext,其他则创建AnnotationConfigApplicationContext,下面就刷新环境。

通过createWebServer();创建web服务

从beanFactory中获得类型为ServletWebServerFactory的组件

通过Spring的bean的创建流程(Spring中bean的创建流程在https://blog.csdn.net/qq_36625757/article/details/83929287这篇博客中有介绍)创建ServletWebServerFactory

在bean的初始化之前会调用所有后置处理器的postProcessBeforeInitialization()方法

发现我们之前讲的WebServerFactoryCustomizerBeanPostProcessor后置处理器也在其中,所以就会调用postProcessBeforeInitialization()方法创建Tomcat,启动Tomcat

3.总结

应用在启动时先通过createWebServer();创建web服务,通过getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);获得类型为ServletWebServerFactory的组件,在ServletWebServerFactory的创建后,初始化前,会调用WebServerFactoryCustomizerBeanPostProcessor后置处理器的postProcessBeforeInitialization()方法,在postProcessBeforeInitialization()方法中,获得类型为WebServerFactoryCustomizer的组件,调用他们的customize()方法,在customize()方法中,通过ServerProperties对servlet容器进行配置,配置后启动Servlet容器。Servlet容器的创建启动后·,在将容器中其他的为创建的bean创建出来,例如:service,controller等。如有错误,请留言改正。

展开阅读全文

没有更多推荐了,返回首页