1.上两编曲讲启动过程,好像并没有涉及到内置tomcat的启动,tomcat是怎么启动的呢?回去看看容器最先初始化的动作
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//检测是否存在web环境
this.webEnvironment = deduceWebEnvironment();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
private boolean deduceWebEnvironment() {
// private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
// "org.springframework.web.context.ConfigurableWebApplicationContext" };
//判断以上两个类是否都存在,如果都存在,webEnviroment设为true
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return false;
}
}
return true;
}
如果是webEnviroment环境又会怎么做呢?在SpringApplication.run方法中,最终可以跟到这么一段代码
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
//如果是web环境则创建AnnotationConfigEmbeddedWebApplicationContext,
//否则创建AnnotationConfigApplicationContext
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);
}
据AnnotationConfigEmbeddedWebApplicationContext名称可以看出这个是可web容器context,那么接下来就看该类及其相关父类就差不多了
直接观察,发现tomcat的启动实现并没有在AnnotationConfigEmbeddedWebApplicationContext,而是在其上一及父类EmbeddedWebApplicationContext
protected void onRefresh() {
super.onRefresh();
try {
//观察不难发现,这里就是创建servlet容器的开始的地方
createEmbeddedServletContainer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start embedded container",
ex);
}
}
private void createEmbeddedServletContainer() {
EmbeddedServletContainer localContainer = this.embeddedServletContainer;
ServletContext localServletContext = getServletContext();
if (localContainer == null && localServletContext == null) {
//通过工厂模式,创建内置的servlet容器,他建完在哪里启动?大概跟applicationcontext生命周期方法就可以跟到了
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();
}
@Override
protected void finishRefresh() {
super.finishRefresh();
//启动servlet容器,到此基本是tomcat启动全过程了
EmbeddedServletContainer localContainer = startEmbeddedServletContainer();
if (localContainer != null) {
publishEvent(
new EmbeddedServletContainerInitializedEvent(this, localContainer));
}
}