springboot(八) 嵌入式Servlet容器自動配置原理和容器啟動原理


1.嵌入式Servlet容器自動配置原理

1.1 在spring-boot-autoconfigure-1.5.9.RELEASE.jar => springboot自動配置依賴 jar包下,EmbeddedServletContainerAutoConfiguration => 嵌入式servlet容器自動配置類

 

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication  //如果是web應用,當前配置類生效
@Import(BeanPostProcessorsRegistrar.class) //Bean后置處理器的注冊器;給容器中注入一些組件
//導入了EmbeddedServletContainerCustomizerBeanPostProcessor
//后置處理器功能:在bean初始化前后(剛創建完對象,還沒屬性賦值)執行初始化工作
public class EmbeddedServletContainerAutoConfiguration { /** * Nested configuration if Tomcat is being used. */ @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(); } }

1.2 EmbeddedServletContainerFactory(嵌入式servlet容器工廠)

public interface EmbeddedServletContainerFactory {
    //獲取嵌入式servlet容器 EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... var1); }

1.3 EmbeddedServletContainer(嵌入式servlet容器)

 1.4 以TomcatEmbeddedServletContainerFactory為例

    @Override
    public EmbeddedServletContainer getEmbeddedServletContainer(
            ServletContextInitializer... initializers) {
      // 創建Tomcat Tomcat tomcat
= new 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); configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers);
      //將配置好的Tomcat傳入進去。返回一個EmbeddedServletContainer 並且啟動tomcat容器
return getTomcatEmbeddedServletContainer(tomcat); }

1.4.1 我們對server的修改是怎么生效的呢?

ServerPorperties ,EmbeddedServletContainerCustomizer

EmbeddedServletContainerCustomizer幫我們修改了server配置,修改的原理是:

容器中也導入了EmbeddedServletContainerCustomizerBeanPostProcessor

//初始化之前   
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      //如果當前初始化的是一個ConfigurableEmbeddedServletContainer類型的組件
if (bean instanceof ConfigurableEmbeddedServletContainer) { postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean); } return bean; }

private void postProcessBeforeInitialization(
ConfigurableEmbeddedServletContainer bean) {
  //獲取所有的定制器,調用每一個定制器的customize()方法來給servlet容器進行屬性賦值
for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
   if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
this.beanFactory
        //從容器中獲取所有這個類型的組件:EmbeddedServletContainerCustomizer
        //如果要定制一個servlet容器,向容器中添加一個EmbeddedServletContainerCustomizer組件
.getBeansOfType(EmbeddedServletContainerCustomizer.class,
false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}

2.嵌入式Servlet容器啟動原理

 2.1 獲取嵌入式servlet容器工廠 

2.1.1 springboot啟動應用運行run方法

2.1.2 refreshContext(context);springboot刷新ioc容器【創建ioc容器對象,並初始化容器,創建容器中的每一個組件】;如果是web應用創建AnnotationConfigEmbeddedWebApplicationContext容器,否則創建默認的AnnotationConfigApplicationContext容器

2.1.3  refresh(context);刷新剛才創建好的ioc容器;

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

2.1.4 onRefresh(); web的ioc容器重寫了onRefresh()方法;

2.1.5 web ioc容器創建嵌入式servlet容器: createEmbeddedServletContainer();

2.1.6 獲取嵌入式servlet容器工廠 getEmbeddedServletContainerFactory() =>從容器中獲取EmbeddedServletContainerFactory組件

   TomcatEmbeddedServletContainerFactory創建對象,后置處理器一看是這個對象,就獲取所有的定制器,先定制servlet容器的相關配置

2.1.7 使用容器工廠獲取嵌入式servlet容器 this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());

2.1.8 嵌入式servlet容器創建對象並啟動ioc容器;

  先啟動嵌入式servlet容器,再將ioc容器中沒有創建的對象獲取出來;ioc容器啟動的時候創建嵌入式servlet容器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM