命名我们就可以知道它是一个监听者,分析springboot启动流程我们会发现,它其实是用来在整个启动流程中接收不同执行点事件通知的监听者,SpringApplicationRunListener接口规定了SpringBoot的生命周期,在各个生命周期广播相应的事件,调用实际的ApplicationListener类。
源码分析
1.获取所有的监听器
SpringApplicationRunListeners可以理解为一个SpringApplicationRunListener的容器,他将SpringApplicationRunListener的集合以构造方法传入。并赋值给listeners成员变量,然后提供针对listeners成员变量的各种遍历操作方法。
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 构建class数组
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 调用SpringApplicationRunListener构造方法
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
SpringApplicationRunListeners 构造方法的第二个参数便是SpringApplicationRunListeners的集合,SpringApplication中调用构造方法时该参数是通过getSpringFactoriesInstances方法获取的,如下:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
// 加载META-INF/spring.factories中对应监听器配置,并将结果存于Set中(去重)
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 实例化监听器
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
通过方法名便可得知,getSpringFactoriesInstances是用来获取factories配置文件中的注册类,并进行实例化操作。
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
// 获取监听器class
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
// 获取有参构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
// 实例化监听器
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
在上面代码中,实例化监听器时需要有一个默认的构造方法,且构造方法的参数为Class<?>[] parameterTypes。我们向上追踪该参数的来源,会发现该参数的值为Class数组,数组的内容依次为SpringApplication和String [].class。也就是说,SpringApplicationRunListener的实现类必须有默认的构造方法,且构造方法的参数必须依次为SpringApplication和String [].class。
2.SpringApplicationRunListener 源码分析
接口SpringApplicationRunListener是SpringApplication的run方法监听器。SpringApplicationRunListener 提供了一系列的方法,我们可以通过回调这些方法,在启动各个流程时加入指定的逻辑,SpringApplicationRunListener接口方法如下:
public interface SpringApplicationRunListener {
/**
* 当run方法第一次被执行时,会被调用,可以用于非常早期的初始化工作
*/
default void starting() {
}
/**
* 当environment准备完成,在ConfigurableApplicationContext创建之前,该方法被调用
*
*/
default void environmentPrepared(ConfigurableEnvironment environment) {
}
/**
* 当ConfigurableApplicationContext构建完成,资源还未加载时,该方法被调用
*
*/
default void contextPrepared(ConfigurableApplicationContext context) {
}
/**
* 当ConfigurableApplicationContext加载完成,未被刷新之前,该方法被调用
*
*/
default void contextLoaded(ConfigurableApplicationContext context) {
}
/**
* 当ConfigurableApplicationContext刷新并启动后,CommandLineRunner和
* ApplicationRunner未执行之前,该方法被调用
*/
default void started(ConfigurableApplicationContext context) {
}
/**
* 当所有准备工作就绪,run方法执行完毕之前,该方法被调用
*
*/
default void running(ConfigurableApplicationContext context) {
}
/**
* 当应用程序出现错误时,该方法被调用
*
*/
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
我们通过源码可以看出,SpringApplicationRunListener为run方法提供了各个运行阶段的监听事件处理功能。
3.实现类EventPublishingRunListener
EventPublishingRunListener是Spring Boot中针对SpringApplicationRunListener接口的唯一内建实现。EventPublishingRunListener使用内置的SimpleApplicationEventMulticaster来广播在上下文刷新之前触发的事件。
默认情况下,SpringBoot在初始化过程中触发的事件也是交由EventPublishingRunListener来代理实现的。EventPublishingRunListener的构造方法如下:
public EventPublishingRunListener(SpringApplication application, String[] args) {
// 当前运行的SpringApplication实例
this.application = application;
// 启动程序时的命令参数
this.args = args;
// 创建SimpleApplicationEventMulticaster广播器
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 遍历ApplicationListener并关联SimpleApplicationEventMulticaster
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
EventPublishingRunListener针对不同的事件停了不同的处理方法,但他们的处理流程基本相同。
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
- 程序启动到某个步骤后,调用EventPublishingRunListener的某个方法
- EventPublishingRunListener的具体方法将application参数和args参数封装到对应的事件中,这里的事件均为SpringApplicationEvent的实现类。
- 通过成员变量initialMulticaster的multicastEvent方法对事件进行广播。或者通过该方法的
ConfigurableApplicationContext参数的publishEvent方法来对事件进行发布。 - 对应的ApplicationListener被触发,执行相应的业务逻辑