从SpringBoot的主类进入SpringApplication的run()方法,然后接着往下分析
1、首先启动一个StopWatch(秒表)
2、配置awt相关
configureHeadlessProperty();
3、从所有的jar包下的META-INF/spring.factories文件中读取所有的org.springframework.boot.SpringApplicationRunListener配置的类名通过反射实例化并保存到SpringApplicationRunListeners的listeners(List<SpringApplicationRunListener> listeners)属性中,并调用SpringApplicationRunListeners的starting方法,既是调用它里面保存的所有的SpringApplicationRunListener的starting方法。
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
4、初始化应用参数和环境变量
5、打印Banner
6、创建应用上下文ApplicationContext。根据当前应用的的类型创建不同的应用上下文,如果是web应用则创建AnnotationConfigServletWebServerApplicationContext,如果是REACTIVE反应式web应用则创建AnnotationConfigReactiveWebServerApplicationContext,否则创建基本的AnnotationConfigApplicationContext。
context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
7、执行一系列的前置方法prepareContext
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
8、属性应用上下文
refreshContext(context);
执行所有的ApplicationContext的父类AbstractApplicationContext的refresh方法,刷新Spring的IOC容器。
@Override
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();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
如果当前是web项目,也即是ServletWebServerApplicationContext,则会调用它的onRefresh()方法,然后再调createWebServer方法,创建嵌入式web服务器,并启动。
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
直到最后完全启动应用。