SpringBoot系列之嵌入式servlet容器啟動原理
嵌入式servlet容器啟動原理
本文將探討以下問題:
什麼時候建立嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啟動Tomcat;
1)、SpringBoot應用啟動執行run方法
2)、refreshContext(context);SpringBoot重新整理IOC容器【建立IOC容器物件,並初始化容器,建立容器中的每一
個元件】;如果是web應用建立:AnnotationConfigEmbeddedWebApplicationContext,否則建立:AnnotationConfigApplicationContext
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); // 建立IOC容器,如果是web應用建立AnnotationConfigEmbeddedWebApplicationContext // 否則建立AnnotationConfigApplicationContext context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 重新整理IOC容器,即建立並初始化容器 refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
3)、refresh(context);重新整理剛才建立好的ioc容器;
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // SpringBoot web的ioc容器重寫了onRefresh方法. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // 原始碼省略 ... } } }
4)、onRefresh(); web的ioc容器重寫了onRefresh方法
5)、webIOC容器會建立嵌入式的Servlet容器;createEmbeddedServletContainer();
6)、獲取嵌入式的Servlet容器工廠:
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
從ioc容器中獲取EmbeddedServletContainerFactory 元件;TomcatEmbeddedServletContainerFactory建立
物件,後置處理器一看是這個物件,就獲取所有的定製器來先定製Servlet容器的相關配置;(注:參考
7)、使用容器工廠獲取嵌入式的Servlet容器:
this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());
8)、嵌入式的Servlet容器建立物件並啟動Servlet容器;
先啟動嵌入式的Servlet容器,再將IOC容器中剩下沒有創建出的物件獲取出來;IOC容器啟動建立嵌入式的Servlet容器
嵌入式的Servlet容器在企業級應用中可能存在一定的侷限性,使用嵌入式Servlet容器:應用需打成可執行的jar
優點:簡單、便攜;
缺點:預設不支援JSP、
優化定製比較複雜(使用定製器【ServerProperties、自定義EmbeddedServletContainerCustomizer】,自己編寫嵌入式Servlet容器的建立工廠【EmbeddedServletContainerFactory】);
在大部分的企業應用中我們可能將專案打成war包,容器的一些引數配置到外接容器上,接下來的文章將探討《外部Servlet容器啟動SpringBoot應用》