启动流程总体分为两步
第一步是SpringApplication构造和初始化完成
第二步是运行run方法
第一步
首先从启动类开始
@SpringBootApplication
public class CmsApplication {
public static void main(String[] args) {
SpringApplication.run(CmsApplication.class, args);
}
}
SpringBootApplication注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的集成,分别表示Springbean的配置bean,开启自动配置spring的上下文,组件扫描的路径,这也是为什么*application.java需要放在根路径的原因,这样@ComponentScan扫描的才是整个项目。
下面我们点进run里面
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
第一个run会执行第二个run,第二个run会执行初始化SpringApplication,点进SpringApplication,最终会执行构造方法SpringApplication,
public SpringApplication(Class<?>... primarySources) {
this((ResourceLoader)null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
首先会设置基础值,后调用initialize方法进行初始化,主要做了几步:
1.将source放入SpringApplication的sources属性中管理,sources是一个LinkedHashSet(),这意味着我们可以同时创建多个自定义不重复的Application,但是目前只有一个。
2.判断是否是web程序(javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext都必须在类加载器中存在),并设置到webEnvironment属性中。
3.从spring.factories中找出ApplicationContextInitializer并设置到初始化器initializers。
4.从spring.factories中找出ApplicationListener,并实例化后设置到SpringApplication的监听器listeners属性中。这个过程就是找出所有的应用程序事件监听器。
5.找出的main方法的类(这里是CmsApplication),并返回Class对象。
到此为止第一步完成。
第二步
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//创建了应用的监听器SpringApplicationRunListeners并开始监听
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//遍历调用
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//加载SpringBoot配置环境(ConfigurableEnvironment),如果是通过web容器发布,会加载StandardEnvironment,其最终也是继承了ConfigurableEnvironment
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//打印banner图标
Banner printedBanner = this.printBanner(environment);
//创建ApplicationContext 并判断是webservice
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//prepareContext方法将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//接下来的refreshContext(context)方法(初始化方法如下)将是实现spring-boot-starter-*(mybatis、redis等)自动化配置的关键,包括spring.factories的加载,bean的实例化等核心工作。
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);//发布ApplicationStartedEvent事件
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);//发布ApplicationReadyEvent事件
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
图片摘抄自:https://www.cnblogs.com/theRhyme/p/11057233.html