springboot【web启动流程-1】
想必⼤家都体验过springboot的便捷,以前想要运⾏web项⽬,我们⾸先需要将项⽬打成war包,然后再运⾏Tomcat启动项⽬,不过⾃从有了springboot,我们可以像启动jar包⼀样简单的启动⼀个web项⽬,今天我们就来分析下springboot启动web项⽬整个流程。
分析springboot,万变不离其中,⼀样从启动⽅法作为⼊⼝
public ConfigurableApplicationContext args) {
context = createApplicationContext();//创建上下⽂
... 略
refreshContext(context);//上下⽂刷新
afterRefresh(context, applicationArguments);
... 略
}
这⾥我们引出了启动相关的两个核⼼⽅法 createApplicationContext 和 refreshContext
⾸先看下createApplicationContext实现:
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
contextClass = Class.forName(this.webEnvironment
DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
我们可以看到context的类型判断逻辑,本⽂我们分析web容器,所以contextClass 为 DEFAULT_WEB_CONTEXT_CLASS
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
+ "bedded.AnnotationConfigEmbeddedWebApplicationContext";
故springboot 的web环境context类 为 AnnotationConfigEmbeddedWebApplicationContext
接着看refreshContext⽅法:
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
... 略
}
AbstractApplicationContext的refresh⽅法
protected void refresh(ApplicationContext applicationContext) {
servlet和tomcat的关系Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
可以看到这⾥最终会调⽤到context的refresh⽅法,⽽我们的AnnotationConfigEmbeddedWebApplicationContext的集成关系图如下:
PS:集成关系过于复杂,这⾥截取了部分重点关系
⽽context的refresh则在AbstractApplicationContext中:
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();
// Initialize other special beans in specific context subclasses.
// 具体的刷新逻辑交由⼦类实现
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();//容器刷新完成之后启动容器
}
}
⽽onRefresh的具体实现在 EmbeddedWebApplicationContext中:
protected void onRefresh() {
try {
//创建内嵌的servlet容器
createEmbeddedServletContainer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start embedded container", ex);
}
}
private void createEmbeddedServletContainer() {
EmbeddedServletContainer localContainer = beddedServletContainer;
ServletContext localServletContext = getServletContext();
// ⾸次启动容器为空
if (localContainer == null && localServletContext == null) {
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();//获取创建容器⼯⼚类
.getEmbeddedServletContainer(getSelfInitializer());//创建容器
}
else if (localServletContext != null) {
try {
getSelfInitializer().onStartup(localServletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
容器创建getEmbeddedServletContainer⽅法实现如下:
public EmbeddedServletContainer getEmbeddedServletContainer(
< initializers) {
Tomcat tomcat = new Tomcat();//新建tomcat
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.AbsolutePath());
Connector connector = new Connector(this.protocol);//新建tomcat容器连接器
customizeConnector(connector);
tomcat.setConnector(connector);
Engine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
}
Host(), initializers);
return getTomcatEmbeddedServletContainer(tomcat);//返回tomcat内嵌容器
}
可以看出 通过onRefresh⽅法最终创建了类型为TomcatEmbeddedServletContainer的web容器,接着我们再来看容器的启动finishRefresh由EmbeddedWebApplicationContext重载实现:
protected void finishRefresh() {
super.finishRefresh();
EmbeddedServletContainer localContainer = startEmbeddedServletContainer();//启动内嵌servlet容器
if (localContainer != null) {
publishEvent(
new EmbeddedServletContainerInitializedEvent(this, localContainer));
}
}
private EmbeddedServletContainer startEmbeddedServletContainer() {
EmbeddedServletContainer localContainer = beddedServletContainer;
if (localContainer != null) {
localContainer.start();
}
return localContainer;
}
到此,springboot启动web容器流程,下⼀篇我们将分析tomcat的启动流程敬请期待...
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论