springboot启动配置原理

重点的事件回调机制

​ 配置在META-INF/spring.factories

  • ApplicationContextListener
  • SpringApplicationRunListener

    在IOC容器中的

  • ApplicationRunner

  • CommandLineRunner

创建SpringApplication对象

调用SpringApplication的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//保存主配置类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
/*判断当前应用的类型,web判断是否存在javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext*/
this.webApplicationType = WebApplicationType.deduceFromClasspath();
/*保存类路径下META-INF/spring.factories得到所有的ApplicationContextInitializer和ApplicationListener类*/
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}

运行Run方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();

//获取SpringApplicationRunListeners 从类路径下META-INF/spring.factories获取
SpringApplicationRunListeners listeners = getRunListeners(args);
//调用所有获取SpringApplicationRunListener的starting方法
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境,创建后回调SpringApplicationRunListener的environmentPrepared
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印图标
Banner printedBanner = printBanner(environment);
//创建ApplicationContext决定创建web的IOC还是普通的IOC
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
/*准备上下文,将上面准备好的环境保存在IOC中,调用applyInitializers(),调用所有的ApplicationContextInitializer的initialize方法,initializer就是上面创建SpringAppication对象时设置好的。
listeners.contextPrepared(context); 再回调所有的SpringApplicationRunListener的contextPrepared()*/
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//prepareContext完成后,回调所有SpringApplicationRunListener的contextLoaded()

//刷新容器:ioc容器初始化
//扫描,创建,加载所有组件的地方
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
//从IOC容器中得到所有ApplicationRunner和CommandLineRunner进行回调
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}