十二、Spring Boot 嵌入式 Servlet 容器啟動原理

丶Dream_RM發表於2018-10-03

什麼時候建立嵌入式 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容器

相關文章