SpringBoot——嵌入式Servlet容器自动配置原理

xiaoxiao2022-06-12  31

Servlet容器自动配置类

在spring-boot-autoconfigure包中有个web模块: 该模块下有个类EmbeddedWebServerFactoryCustomizerAutoConfiguration,负责嵌入式Servlet容器的自动配置,该类的源码:

@Configuration @EnableConfigurationProperties(ServerProperties.class) public class EmbeddedWebServerFactoryCustomizerAutoConfiguration { @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })//判断是否引入了Tomcat依赖,我们默认就是引入的Tomcat public static class TomcatWebServerFactoryCustomizerConfiguration { @Bean public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer( Environment environment, ServerProperties serverProperties) { return new TomcatWebServerFactoryCustomizer(environment, serverProperties); } } /** * Nested configuration if Jetty is being used. */ @Configuration @ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class }) public static class JettyWebServerFactoryCustomizerConfiguration { @Bean public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer( Environment environment, ServerProperties serverProperties) { return new JettyWebServerFactoryCustomizer(environment, serverProperties); } } /** * Nested configuration if Undertow is being used. */ @Configuration @ConditionalOnClass({ Undertow.class, SslClientAuthMode.class }) public static class UndertowWebServerFactoryCustomizerConfiguration { @Bean public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer( Environment environment, ServerProperties serverProperties) { return new UndertowWebServerFactoryCustomizer(environment, serverProperties); } } }

该类中有三个方法:TomcatWebServerFactoryCustomizerConfiguration、JettyWebServerFactoryCustomizerConfiguration、UndertowWebServerFactoryCustomizerConfiguration,这三个方法中都有一个注解@ConditionalOnClass,该注解中标明在引入哪些依赖时就会使相应的XxxCustomizerConfiguration生效,这也是通过修改依赖就可将Servlet容器切换为Tomcat、Jetty和Undertow的原因

旧版本的自动配置

在旧版本的SpringBoot中,会有些不同: 旧版本的web模块下有个EmbeddedServletContainerAutoConfiguration:负责嵌入式Servlet容器的自动配置

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication @Import(BeanPostProcessorsRegistrar.class) //导入BeanPostProcessorsRegistrar:Spring注解版;给容器中导入一些组件 //导入了EmbeddedServletContainerCustomizerBeanPostProcessor: //后置处理器:bean初始化前后(创建完对象,还没赋值赋值)执行初始化工作 public class EmbeddedServletContainerAutoConfiguration { @Configuration @ConditionalOnClass({Servlet.class, Tomcat.class})//判断当前是否引入了Tomcat依赖; @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) //判断当前容器没有用户自己定义EmbeddedServletContainerFactory:嵌入式的Servlet容器工厂;作用:创建嵌入式的Servlet容器 public static class EmbeddedTomcat { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { return new TomcatEmbeddedServletContainerFactory(); } } /** * Nested configuration if Jetty is being used. */ @Configuration @ConditionalOnClass({Servlet.class, Server.class, Loader.class, WebAppContext.class}) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedJetty { @Bean public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() { return new JettyEmbeddedServletContainerFactory(); } } /** * Nested configuration if Undertow is being used. */ @Configuration @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class}) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedUndertow { @Bean public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() { return new UndertowEmbeddedServletContainerFactory(); } } }

EmbeddedServletContainerFactory(嵌入式Servlet容器工厂):

public interface EmbeddedServletContainerFactory { //获取嵌入式的Servlet容器 EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers); }

EmbeddedServletContainerFactory的实现类: EmbeddedServletContainer(嵌入式的Servlet容器): 以TomcatEmbeddedServletContainerFactory为例:

@Override public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); //构建tomcat实例 //配置Tomcat的基本环境 File baseDir = (this.baseDirectory != null ? this.baseDirectory : createTempDir("tomcat")); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); tomcat.getEngine().setBackgroundProcessorDelay(-1); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers); //将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;并且启动Tomcat服务器 return getTomcatEmbeddedServletContainer(tomcat); }

我们对嵌入式容器的配置修改是怎么生效?通过ServerProperties、EmbeddedServletContainerCustomizer,而ServerProperties是EmbeddedServletContainerCustomizer的子类,修改的原理,因为导入了了EmbeddedServletContainerCustomizerBeanPostProcessor,属性赋值是在该类中进行的 步骤: 1、SpringBoot根据导入的依赖情况,给容器中添加相应的 EmbeddedServletContainerFactory(如TomcatEmbeddedServletContainerFactory) 2、容器中某个组件要创建对象就会惊动后置处理器EmbeddedServletContainerCustomizerBeanPostProcessor(只要是嵌入式的Servlet容器工厂,后置处理器就工作) 3、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法给容器的属性赋值

转载请注明原文地址: https://www.6miu.com/read-4932297.html

最新回复(0)