Spring Boot4-2 --嵌入式Servlet容器自动配置原理(Spring Boot版本2.1.3)(理解原理)

springBoot 默认使用的是tomcat
在导入的依赖中:autoconfigure 中的web 目录下所有含有Server的类都与Servlet容器的相关
笔记的原理分析基于Spring Boot2.1.3版本;2.0 以下版本的一些类被代替

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

主要的三个类:
在这里插入图片描述

1.ServletWebServerfactoryConfihration

有三个:EmbeddedUndertow ,EmbeddedJetty,EmbeddedTomcat @Conditionalxxx 标注的类;条件满足才向容器中添加组件
例如:添加tomcat

@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})
@ConditionalOnMissingBean(
    value = {ServletWebServerFactory.class},
    search = SearchStrategy.CURRENT
  )
  public static class EmbeddedTomcat {
      public EmbeddedTomcat() {
       }

    @Bean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
    return new TomcatServletWebServerFactory();
       }
    }

重要注解详解:

1. @ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})

   容器中存在servlet.class(存在servlet依赖)  tomcat.class(tomcat依赖)  才能执行向容器中添加组件
   
2. @ConditionalOnMissingBean(value = {ServletWebServerFactory.class},search = SearchStrategy.CURRENT )
    判断容器中没有用户自定义的ServletWeServerbFactory

ServletWebServerFactory
嵌入式Servlet工厂;作用:创建嵌入式Servlet容器
容器工厂:
Spring Boot4-2 --嵌入式Servlet容器自动配置原理(Spring Boot版本2.1.3)(理解原理)_第1张图片继承树

当中只有一个方法:获取嵌入式Servlet容器 (WebServer)
public interface ServletWebServerFactory {
    WebServer getWebServer(ServletContextInitializer... var1);
}

容器工厂包含了:TomcatServletWebServerFactory,JettyServletWebServerFactory,UndetowServletWebServerFactory
webServr 嵌入式Servlet容器:
Spring Boot4-2 --嵌入式Servlet容器自动配置原理(Spring Boot版本2.1.3)(理解原理)_第2张图片继承树

在判断@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})是否导入依赖,满足条件: return new TomcatServletWebServerFactory(); 添加对应的Servlet容器工厂;通过工厂的唯一方法getWebServer 获取对应的Servlet容器TomcatServer

TomcatServletWebServerFactory
tomcat 的容器工厂

在工厂中获取tomcat 的方法:getWebServer

 public WebServer getWebServer(ServletContextInitializer... initializers) {
       1. 创建Tomcat对象       
         Tomcat tomcat = new Tomcat();      
           
        File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        
      2.完成tomct 配置的基本操作
        Connector connector = new Connector(this.protocol);
        tomcat.getService().addConnector(connector);
        this.customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        this.configureEngine(tomcat.getEngine());
        Iterator var5 = this.additionalTomcatConnectors.iterator();

        while(var5.hasNext()) {
            Connector additionalConnector = (Connector)var5.next();
            tomcat.getService().addConnector(additionalConnector);
        }

        this.prepareContext(tomcat.getHost(), initializers);
        
      3.将tomcat 传入方法:getTomcatWebServer()
        return this.getTomcatWebServer(tomcat);
    }
getTomcatWebServer()
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
        return new TomcatWebServer(tomcat, this.getPort() >= 0);  端口>0  就创建Tomcat 容器
    }

TomcatWebServer

对应的构造函数:在TomcatWebServer 中
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
       this.monitor = new Object();
       this.serviceConnectors = new HashMap();
       Assert.notNull(tomcat, "Tomcat Server must not be null");
       this.tomcat = tomcat;
       this.autoStart = autoStart;   自动启动变量
       this.initialize();
   }

方法:initialize()核心代码:
this.tomcat.start();    启动Tomcat

至此Tomcat就完成了配置和自动启动

2.ServletWebServerFactoryAutoConfiguration

修改定制Servlet 容器的方法:
配置文件和ServerProperties 绑定/修改定制组件 WebServerFactoryCustomizer
他们的本质是一样的:在ServletWebServerFactoryAutoConfiguration配置类中@EnableConfigurationProperties({ServerProperties.class})

导入了:BeanPostProcessorsRegistrar;在这个类的方法中添加了组件WebServerFactoryCustomizerBeanPostProcessor定制器后置处理器

也就是说一旦容器中添加任何组件都会启动定制后置处理器,进行Servlet的赋值

后置处理器起作用的过程:

在初始化之前:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   如果组件创建的对象是:WebServerFactory 就调用postProcessBeforeInitialization
        if (bean instanceof WebServerFactory) {       
            this.postProcessBeforeInitialization((WebServerFactory)bean);
        }

        return bean;
    }
解释:
自定义定制器:  
  @Bean
 public WebServerFactoryCustomizer MyCustomizer(){
return new WebServerFactoryCustomizer() {... }
}
public interface WebServerFactoryCustomizer {
    void customize(T var1);
} 

ConfigurableWebServerFactory继承WebServerFactory ;所以修改数据的时候创建了WeServerFactory
自动配置的时候也会创建对应的工厂对象
postProcessBeforeInitialization
核心语句:
    customizer.customize(webServerFactory);
获取spring Boot中所有的WebServerFactoryCustomizer 这个类型的定制器通过定制方法:customize()给Servlet容器赋值
同时这也是为什么自定义修改配置组件是自定义的WebServerFactoryCustomizer

3.ServletWebServerFactoryCustomizer

在这个配置类中:

private final ServerProperties serverProperties;

同时使用了:

 public void customize(ConfigurableServletWebServerFactory factory) {
 完成了Tomcat的各项配置的修改和定制

总结配置修改定制原理:以tomcat为例

  1. 使用修改定制器 webServerFactoryCustomizer 创建了ConfigurableWebServerFactory 对象,触发WebServerFactoryCustomizerBeanPostProcessor 后置处理器,判断是否为WebServerFactory 类型;

    ConfiurableWebServerFactory 继承webServerFactory

    满足条件,就会获取容器中的所有定制器(customizer.cutomize(bean)),为Servlet容器修改和定制配置【相关的配置类ServletWebServerFactoryAutoConfiguration;导入了定制处理器】

  2. 使用配置文件application.propertoes 修改配置。server 相关的配置修改是与ServerProperties 类绑定的,所以相关的修改会直接通过Serverproperties 的方法实现【相关的配置类:ServletWebServerFactoryCustomizer】


嵌入式Servlet 容器启动的原理(tomcat)

  1. SpringBoot 应用启动,运行run方法
  2. refreshContext(context) 刷新ioc 容器。创建web 应用的ioc 容器对象,并初始化容器
  3. 获取工厂容器组件:ServletWebServerFactory factory = this.getServletWebServerFactory ();
    tomcatServeltWebServerFactory 创建,触发后置处理器,配置类中:@EnableConfigurationProperties({ServerProperties.class}) 根据配置文件,获取所有的定制器为Sevlet容器赋值
  4. tomcatServerWebServletFactory 获取完成;获取TomcatWebServer 完成自启动

总结图示:
Spring Boot4-2 --嵌入式Servlet容器自动配置原理(Spring Boot版本2.1.3)(理解原理)_第3张图片
学习的目的:会自己定制修改Servlet 容器的配置

你可能感兴趣的:(Spring,Boot)