Springboot事件监听机制

监听器模式4要素

  1. 事件
  2. 监听器
  3. 广播器
  4. 触发机制

SpingBoot 实现

系统监听器
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;
    }
}

在这里插入图片描述
Springboot事件监听机制_第1张图片
事件发送顺序
Springboot事件监听机制_第2张图片
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

Application Listeners

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))
}

Springboot事件监听机制_第3张图片

Springboot事件监听机制_第4张图片
Springboot事件监听机制_第5张图片
Springboot事件监听机制_第6张图片
Springboot事件监听机制_第7张图片

你可能感兴趣的:(spring,boot,java,spring)