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