系统监听器
org.springframework.context.ApplicationListener
@FunctionalInterface //只能有一个方法
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
通过实现这个接口去监听事件,遵循 java.util.EventListener 标准
Spring 事件,触发感兴趣的监听器。当监听到事件发生的时候,去执行具体的事情
系统广播器 管理监听器(添加/删除),广播事件
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> var1);
void addApplicationListenerBean(String var1);
void removeApplicationListener(ApplicationListener<?> var1);
void removeApplicationListenerBean(String var1);
void removeAllListeners();
void multicastEvent(ApplicationEvent var1);
void multicastEvent(ApplicationEvent var1, @Nullable ResolvableType var2);
}
Spring系统事件
org.springframework.boot.context.event.ApplicationPreparedEvent
public class ApplicationPreparedEvent extends SpringApplicationEvent {
private final ConfigurableApplicationContext context;
public ApplicationPreparedEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context) {
super(application, args);
this.context = context;
}
public ConfigurableApplicationContext getApplicationContext() {
return this.context;
}
}
事件发送顺序
Starting ApplicationStartingEvent 框架一启动就发出
EnvironmentPrepared ApplicationEnvironmentPreparedEvent 环境准备好,spring容器的系统属性和指定的属性已加载到容器内
ContextInitialized ApplicationContextInitializedEvent 启动并且准备好了应用上下文 加载Bean 定义之前发布的
Prepared ApplicationPreparedEvent 应用上下文已经创建完毕,但Bean 还没完全加载完成
Started ApplicationStartedEvent 把Bean 实例化完成,但还没有调用 ApplicationRunner 和 CommandLineRunner 扩展接口
Ready ApplicationReadyEvent 调用完 ApplicationRunner 和 CommandLineRunner 扩展接口之后
Faild ApplicationFailedEvent 过程中出现失败
SpringBoot 启动流程
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.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();
}
setListeners方法,就是将所有配置在spring.factories文件中,key值为 org.springframework.context.ApplicationListener的类实例化后,设置到SpringApplication对象的listeners属性当中。
没有任何添加的情况下,分别从不同的spring依赖中获取
spring.factories
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
以分析 Starting 为例
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
}
通过SpringFactoriesLoader 扫描加载 META-INF/spring.factories
SpringFactoriesLoader是Spring的一个内部加载工厂类,我们自定义的一些ApplicationListener、ApplicationContextInitializer可以通过它加载到内存中,同时starter也必须通过SpringFactoriesLoader把Configuration类加载到内存中
public ConfigurableApplicationContext run(String ...args){
listeners.starting()
}
public void starting(){
for(SpringApplicationRunListener listener:this.listeners){
listener.starting()
}
}
SpringApplicationRunListener定义了Spring各个阶段的事件,内部实际调用了广播器去发送事件
实现监听器的内部调用和外部实现隔离
public void starting(){
//广播器
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application,this.args))
}