一、启动方法
二、进入run方法,跟踪下去发现他先调用一个初始化方法initialize
①sources 就是你的启动对象
②deduceWebEnvironment()判断是否是web环境,原理就是判断如下的两个类是否存在,存在就是web环境
③getSpringFactoriesInstances方法在springboot里大量使用,他的作用是从spring的autoconfig包里的META-INF下的spring.factories文件中加载指定接口的所有实现类。例如:getSpringFactoriesInstances(ApplicationContextInitializer.class)这句代码,实际是去加载如下的类
④setInitializers 把加载到的类放到一个list里头去
⑤setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));这行代码原理同③④,不做重复讲解
⑥deduceMainApplicationClass 作用是获取启动类
三、看完初始化方法,接下来就是调用run方法了
public ConfigurableApplicationContext run(String... args) {
//时钟工具,用来计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//ApplicationContext的子类,比父类拥有更加丰富的方法,具体的以后分享spring原理的时候再说
ConfigurableApplicationContext context = null;
//异常报告,后面调用时候详细说明
FailureAnalyzers analyzers = null;
//设置无头模式,我也不太懂,自行百度,好像说是让电脑自己模拟外接设备
configureHeadlessProperty();
//去spring.factories里加载SpringApplicationRunListener接口的实现类,其实这里说是listener,实际上SpringApplicationRunListener更像一个发布者publish,他的作用是发布各自事件
SpringApplicationRunListeners listeners = getRunListeners(args);
//spring的观察者模式模板,在springboot启动过程用了很多这样通知的地方,下一章将用一章来讲解各个listener
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//这一步获取启动命令里的配置和具体要使用哪个环境的配置文件,就是根据sprring.active.profiles来加载配置文件。但是这里要注意命令里的配置会记录到enviroment里,但是配置文件,该行代码仅仅是记录你是用哪个文件。(说得够清楚了吧)
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//打印banner
Banner printedBanner = printBanner(environment);
//根据是否是web项目创建不同的applicationcontext
context = createApplicationContext();
//这儿也是去spring.factories里加载好多失败分析器,这个也单独拿一个篇幅讲吧。这篇主要是通体脉络,细节会拆分到各个子篇幅里去讲。
analyzers = new FailureAnalyzers(context);
//这里会把我们之前初始化时候加载的初始化类都执行一遍,后面专门开一个讲每个初始化类的作用
//以及会把启动类加载到spring容器里去,这样我们第一章讲的注解就能生效了。
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//调用spring的refresh方法
refreshContext(context);
//查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}