Spring Boot 嵌入式 Servlet 容器啟動原理
什麼時候建立嵌入式 Servlet 容器工廠? 什麼時候獲取嵌入式 Servlet 容器並啟動服務?
1)、Spring Boot 應用啟動執行 run(); 方法
2)、refreshContext(context); Spring Boot重新整理 IOC 容器(建立 IOC容器物件並初始化,建立容器中的每一個元件), 如果是 WEB 應用 建立的是 org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext 容器; 如果不是 建立的是 org.springframework.web.context.ConfigurableWebApplicationContext
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(); } } }
4)、this.onRefresh(); WEB 的 IOC 容器重寫了 onRefresh() 方法
5)、 WEB 的 IOC 容器會建立 嵌入式的 Servlet 容器
@Override protected void onRefresh() { super.onRefresh(); try { createEmbeddedServletContainer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start embedded container", ex); } }
6)、獲取嵌入式的Servlet容器工廠: EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
private void createEmbeddedServletContainer() {
EmbeddedServletContainer localContainer = this.embeddedServletContainer;
ServletContext localServletContext = getServletContext();
if (localContainer == null && localServletContext == null) {
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
this.embeddedServletContainer = containerFactory
.getEmbeddedServletContainer(getSelfInitializer());
}
else if (localServletContext != null) {
try {
getSelfInitializer().onStartup(localServletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
從 IOC 容器中獲取 EmbeddedServletContainerFactory 元件;此時專案start 裡面有哪個的依賴,就建立對應的物件:XXXXEmbeddedServletContainerFactory,後置處理器起作用,獲取所有的定製器來定製 Servlet 容器的相關配置
7)、使用容器工廠獲取嵌入式的Servlet 容器: this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());
private void createEmbeddedServletContainer() {
EmbeddedServletContainer localContainer = this.embeddedServletContainer;
ServletContext localServletContext = getServletContext();
if (localContainer == null && localServletContext == null) {
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
this.embeddedServletContainer = containerFactory
.getEmbeddedServletContainer(getSelfInitializer());
}
else if (localServletContext != null) {
try {
getSelfInitializer().onStartup(localServletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
8)、嵌入式的Servlet容器建立物件並且啟動
Spring Boot是先啟動嵌入式的Servlet容器,再將 IOC 容器中沒有建立的物件獲取出來
IOC容器啟動建立嵌入式Servlet容器