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

Servlet容器自动配置类

在spring-boot-autoconfigure包中有个web模块:
SpringBoot——嵌入式Servlet容器自动配置原理_第1张图片
该模块下有个类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的实现类:
SpringBoot——嵌入式Servlet容器自动配置原理_第2张图片
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,调用定制器的定制方法给容器的属性赋值

你可能感兴趣的:(SpringBoot)