1. 说明

springboot的生命周期主要在springboot启动容器阶段的扩展,从容器刷新开始主要就是spring相关的扩展了

看过springboot源码就应该知道,我们从pringApplication.run()启动springboot工程,其有一个初始化器、监听器、一个异常报告器
同时,springboot还支持在启动之后执行初始化方法,相当于在容器启动之后执行方法, 防止方法报错导致容器起不来

2. 扩展

2.1. 初始化器ApplicationContextInitializer

初始化器在上下文设置好环境变量之后执行,在这里可以操作环境变量相关信息;
实际上类信息是spring的相关扩展,只是springboot在启动时会加载这个扩展

ApplicationContextInitializer有道翻译:这里封装了配置和生命周期方法,以避免让ApplicationContext客户端代码明显看到它们。目前的方法应该只用于启动和关闭代码。

2.1.1. 使用

首先实现ApplicationContextInitializer,然后在classpath:META-INF/spring.factories中配置实例

  • java代码
1
2
3
4
5
6
7
8
9
10
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class MyContextApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println(applicationContext.getApplicationName());
}
}

  • META-INF/spring.factories配置
1
org.springframework.context.ApplicationContextInitializer=com.kewen.demo.boot.config.MyContextApplicationContextInitializer

2.1.2. 解析

SpringApplication#prepareContext()时会加载环境变量到上下文中,然后执行初始化器

1
2
3
4
5
6
7
8
private void prepareContext(ConfigurableApplicationContext context , ......) {
//准备环境变量
context.setEnvironment(environment);
//加载ResourceLoader、ClassLoader、ConversionService等
postProcessApplicationContext(context);
applyInitializers(context);
......
}

2.2. 应用启动监听器SpringApplicationRunListeners监听springboot启动全流程,各个阶段都有监听方法

springboot启动的生命周期监听器,在各个阶段均会执行

2.2.1. 使用

  • java代码

java中必须包含传入SpringApplication主类和args传入参数 的构造器,否则报错

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

public class MyBootSpringApplicationRunListener implements SpringApplicationRunListener {

SpringApplication springApplication;
String[] args;

/**
* 构造函数
* @param springApplication main函数创建的实例
* @param args 传入的参数
*/
public MyBootSpringApplicationRunListener(SpringApplication springApplication, String[] args) {
this.springApplication = springApplication;
this.args = args;
}

/**
* 启动中
*/
@Override
public void starting() {
SpringApplicationRunListener.super.starting();
}

/**
* 环境变量已经准备好
* @param environment the environment
*/
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
SpringApplicationRunListener.super.environmentPrepared(environment);
}

/**
* 上下文以准备好
* @param context the application context
*/
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
SpringApplicationRunListener.super.contextPrepared(context);
}

/**
* 上下文已加载
* @param context the application context
*/
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
SpringApplicationRunListener.super.contextLoaded(context);
}

/**
* 应用已启动
* @param context the application context.
*/
@Override
public void started(ConfigurableApplicationContext context) {
SpringApplicationRunListener.super.started(context);
}

/**
* 运行中
* @param context the application context.
*/
@Override
public void running(ConfigurableApplicationContext context) {
SpringApplicationRunListener.super.running(context);
}

/**
* 运行失败
* @param context the application context or {@code null} if a failure occurred before
* the context was created
* @param exception the failure
*/
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
SpringApplicationRunListener.super.failed(context, exception);
}
}

  • META-INF/spring.factories配置
1
org.springframework.boot.SpringApplicationRunListener=com.kewen.demo.boot.config.MyBootSpringApplicationRunListener

2.2.2. 解析

SpringApplication的各个阶段执行,具体可以看源码解析

2.3. ApplicationListener 应用上下文监听器

此监听器是spring-context中的监听器,用于监听上下文变化,springboot的SpringApplicationRunListener有一个特殊的监听器EventPublishingRunListener,会在上下文发生变化的时候创建不同的实例并发布出去,
若有ApplicationListener监听到对应的事件,也会执行操作,因此可以通过此spring自带的监听实现应用启动监听

2.3.1. 使用

  • java代码
1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class MyContextApplicationListener implements ApplicationListener {

/**
* @param event 可以是ApplicationEvent的任意实现类
*/
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("ApplicationListener监听器实例:"+event.getClass().getName());
}
}

ApplicationEvent 可以是以下实例:
org.springframework.boot.context.event.ApplicationStartingEvent org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent org.springframework.boot.context.event.ApplicationContextInitializedEvent org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent org.springframework.context.event.ContextRefreshedEvent org.springframework.boot.context.event.ApplicationStartedEvent org.springframework.boot.availability.AvailabilityChangeEvent org.springframework.boot.context.event.ApplicationReadyEvent org.springframework.boot.availability.AvailabilityChangeEvent

  • META-INF/spring.factories配置
1
org.springframework.context.ApplicationListener=com.kewen.demo.boot.config.MyContextApplicationListener

2.3.2. 解析

主要是类EventPublishingRunListener,监听到不同的事件的同时发布不同的spring事件

2.4. SpringBootExceptionReporter 错误报告

**有道翻译:**用于支持自定义SpringApplication启动错误报告的回调接口。reporters通过springfactoresloader加载,并且必须声明一个带有单个ConfigurableApplicationContext参数的公共构造函数。

2.4.1. 使用

  • java代码
1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.boot.SpringBootExceptionReporter;
import org.springframework.context.ConfigurableApplicationContext;

public class MyBootSpringBootExceptionReporter implements SpringBootExceptionReporter {
ConfigurableApplicationContext context;
public MyBootSpringBootExceptionReporter(ConfigurableApplicationContext context) {
this.context = context;
}
@Override
public boolean reportException(Throwable failure) {
return false;
}
}
  • META-INF/spring.factories配置
1
org.springframework.boot.SpringBootExceptionReporter=com.kewen.demo.boot.config.MyBootSpringBootExceptionReporter

2.5. ApplicationRunnerCommandLineRunner

用于springboot应用启动后执行初始化操作,直接注入到容器中就可以了

2.5.1. 使用

ApplicationRunner

1
2
3
4
5
6
7
@Component
public class MyBootApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(args);
}
}

CommandLineRunner

1
2
3
4
5
6
7
@Component
public class MyBootCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println(args);
}
}

2.5.2. 解析

在springboot启动完成的最后,执行callRunners

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}

总结

springboot主要是一些全局的启动生命周期函数,不是bean生命周期,主要提供一些扩展点,因此不容易根据生命周期划分(如ApplicationListener是监听事件的,很多地方都会调用到)
ApplicationListener
ApplicationContextInitializer
SpringApplicationRunListener
SpringBootException
ApplicationRun
CommandLineRunner

加上spring的周期函数,如图:

spring周期函数