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容器