在Spring Boot的自动配置包下,找到web模块中的servlet文件夹下的ServletWebServerFactoryConfiguration类
一、嵌入式Servlet容器默认的配置原理
1、该类中有三个静态内部类(都是配置类):
EmbeddedUndertow、EmbeddedJetty、EmbeddedTomcat
这里拿EmbeddedTomcat来举例说明
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
判断classpath下有没有Servlet, Tomcat, UpgradeProtocol这三个类,也就是看maven有没有引入对应的依赖,如果引入了对应的依赖,下面的配置就生效。(上一篇文章SpringBoot切换嵌入式容器就是根据这里来的链接)
![v2-a108d1a9a9df8dc8fce4ef926db3cec4_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-a108d1a9a9df8dc8fce4ef926db3cec4_b.jpg)
2、@ConditionalOnMissingBean(
value = {ServletWebServerFactory.class},
search = SearchStrategy.CURRENT
)
如果容器中没有ServletWebServerFactory这个组件下面的配置就生效
点进ServletWebServerFactory看,该接口只有一个方法,前面只判断这个类型的组件有没有在容器中,而该类型又只有一个方法,说明最终Spring Boot会调用该接口实现类中的getWebServer方法。
![v2-af8ef859b57aed00a48fff82d1032dc8_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-af8ef859b57aed00a48fff82d1032dc8_b.jpg)
![v2-8274f4d3f353159f34cf6901b0b050e4_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-8274f4d3f353159f34cf6901b0b050e4_b.jpg)
3、查看ServletWebServerFactory接口的实现,有三个很面熟的实现类,就是上面ServletWebServerFactoryConfiguration类中要往容器中添加的组件
![v2-2e938b77bd7ce739d0780015bd5d930e_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-2e938b77bd7ce739d0780015bd5d930e_b.jpg)
![v2-5dc7c14e50d3e6da523eba04f70eaa9d_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic2.zhimg.com/v2-5dc7c14e50d3e6da523eba04f70eaa9d_b.jpg)
4、进入TomcatServletWebServerFactory类中查看getWebServer方法
首先会创建一个Tomcat对象,给其设置连接器等一些配置
最终还会调用getTomcatWebServer方法
this.getTomcatWebServer(tomcat);
-->return new TomcatWebServer(tomcat, this.getPort() >= 0);
端口号默认是8080所以上面传过去的是true,进入TomcatWebServer的构造方法TomcatWebServer中,在构造方法中又调用了this.initialize();进入initialize方法,该方法就会启动tomcat。(所以这一切都是建立在创建好嵌入式Servlet容器之后)
![v2-b94f08bb2764e71de2f26116c7ccba78_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-b94f08bb2764e71de2f26116c7ccba78_b.jpg)
![v2-817280b3fbe40cb008d5e4518c26c032_b.png](http://img-02.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-817280b3fbe40cb008d5e4518c26c032_b.png)
![v2-730d1b0223f923f35aece578a21d2df3_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-730d1b0223f923f35aece578a21d2df3_b.jpg)
![v2-4c8df582fcba2e0352e87ab5ede601cc_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-4c8df582fcba2e0352e87ab5ede601cc_b.jpg)
二、修改SpringBoot初始化嵌入式Servlet容器的默认配置原理
上一篇文章(链接)中我们自己配置个WebServerFactoryCustomizer<ConfigurableWebServerFactory>组件就可以实现修改SpringBoot初始化嵌入式Servlet容器的默认配置了,下面开始说怎么修改其默认配置的。
在ServletWebServerFactoryAutoConfiguration类上面有
@EnableConfigurationProperties,@Import注解
![v2-d1386adb06d7e9ccfaf06c6e4e7a2732_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-d1386adb06d7e9ccfaf06c6e4e7a2732_b.jpg)
1、@EnableConfigurationProperties({ServerProperties.class})
把ServerProperties注册到容器中,并读取全局配置文件中的数据赋值给类中的属性。
只有一个有参构造,形参的值(serverProperties)会从容器中获取,最终交给ServletWebServerFactoryCustomizer类,进入ServletWebServerFactoryCustomizer类
该类也是WebServerFactoryCustomizer的子类
里面有个customize方法会把从容器中获取到的servlerProperties中的值拿出来然后一个一个的设置给factory,最后交给那个map。
![v2-3683ccf2051ff70f809216125060b24a_b.png](http://img-02.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-3683ccf2051ff70f809216125060b24a_b.png)
![v2-549c2c7372c2cce32a87c5f5a71efe42_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-549c2c7372c2cce32a87c5f5a71efe42_b.jpg)
2.1、通过@Import往容器中导入了一个BeanPostProcessorsRegistrar类,该类中的作用是
bean注册后置处理器:Bean初始化前后(创建好对象,还没赋值)执行初始化工作(容器中某个组件要创建bean,就会惊动后置处理器,容器中要创建bean这个才会触发,下面的方法才会被调用)
![v2-2dc9e03f6f20db450c878c689edf13bc_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-2dc9e03f6f20db450c878c689edf13bc_b.jpg)
2.2、进入BeanPostProcessorsRegistrar类查看registerBeanDefinitions方法(注册bean的定义),然后调用registerSyntheticBeanIfMissing方法
![v2-f3237a76fe698689c08f747324600ea2_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-f3237a76fe698689c08f747324600ea2_b.jpg)
2.3、我们点进WebServerFactoryCustomizerBeanPostProcessor类中只需要看postProcessBeforeInitialization方法,在bean创建好之后,初始化之前的调用的方法,该方法首先会判断当前的bean如果为WebServerFactory类型(我们前面需要往容器中注册三个嵌入式Servlet容器就是该接口的实现类,所以当前这个bean就是嵌入式的Servlet容器),就调用postProcessBeforeInitialization方法
![v2-5e6972624ac8c77bdfb8abcd125da353_b.png](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic4.zhimg.com/v2-5e6972624ac8c77bdfb8abcd125da353_b.png)
2.4、进入postProcessBeforeInitialization方法,该方法会获得所有的定制器,然后遍历,调用每个定制器的customize方法,并把嵌入式的Servlet容器传进去。
上一篇文章(链接)中我们修改嵌入式的Servlet容器的配置也是往容器中添加一个WebServerFactoryCustomizer组件,并在其customize方法中修改配置。
在前面说到通过配置文件来修改配置也是在WebServerFactoryCustomizer的子类中重写了
customize方法,并在其customize方法中修改配置。
回到这里的postProcessBeforeInitialization方法,我们这里把嵌入式的Servlet容器传过去,调用所有定制器的customize方法,不就是调用的上面两种修改配置的重写后的customize方法吗,我们在重写后的customize方法中对参数进行设置值,就是对我们这里传过去的嵌入式Servlet容器设置值,最终通过全局配置文件中配置和往容器中添加一个WebServerFactoryCustomizer组件就可以达到修改嵌入式的Servlet容器的默认值了
![v2-564a26c76f9b14a5a04db2b586e6d352_b.png](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic3.zhimg.com/v2-564a26c76f9b14a5a04db2b586e6d352_b.png)
![v2-31e6b76e737680d19bee4368d116debc_b.jpg](http://img-02.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-31e6b76e737680d19bee4368d116debc_b.jpg)
往容器中添加一个WebServerFactoryCustomizer组件
![v2-07aedd4d341067b0142a508a5e491a68_b.jpg](http://img-03.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-07aedd4d341067b0142a508a5e491a68_b.jpg)
前面说到的,经过一系列的逻辑最终全局配置文件中的值会在这里给嵌入式的Servlet容器进行赋值
![v2-a2005659ad7b3965a794d7cee320268c_b.jpg](http://img-01.proxy.5ce.com/view/image?&type=2&guid=cff7804d-2a2f-eb11-8da9-e4434bdf6706&url=https://pic1.zhimg.com/v2-a2005659ad7b3965a794d7cee320268c_b.jpg)
注:看完这一篇文章要结合下一篇文章来理解