Springboot listener

 

在启动流程中,会出发许多ApplicationEvent。这时会调用对应的listener的onApplicationEvent方法。ApplicationEvent时观察者模式, 

(1) 实体继承ApplicationEvent

(2) 注入的Listener 实现接口ApplicationListener, 触发后的处理逻辑在onApplicationnEvent中

(3) 事件发起方通过ApplicationContext 实例的publishEvent方法将 (1)的实体传入(2)

 

SpringBoot 启动时的入口方法SpringApplication.run 内部实现为

    public static ConfigurableApplicationContext run(Class<?>[] primarySources,
            String[] args) {
        return new SpringApplication(primarySources).run(args);
    }

第一步 new SpringApplication 内部会注入系统Listener  具体的listeners参见 https://blog.csdn.net/zl1zl2zl3/article/details/79765725

this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

第二步 调用 run(args)  启动Listener

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();

第二步 2.1 如何获取监听器:在getRunListeners中会读取配置文件,加载的是Springboot META-INF/spring.factories 中的 org.springframework.boot.context.event.EventPublishingRunListener, 并生成"事件发布启动监听器"的工厂实例

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
            SpringApplicationRunListener.class, types, this, args));
}

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
    return getSpringFactoriesInstances(type, new Class<?>[] {});
}

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
        Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    // 使用Set确保的字符串的唯一性
    Set<String> names = new LinkedHashSet<String>(
            SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 1.载入工厂名称集合
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes,// 2.创建工厂实例
            classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);// 排序
    return instances;
}

META-INF/spring.factories

# Run Listeners  这里呢,看这里!!!!
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

 

第二步 2.2 启动监听 starting()

SpringApplicationRunListeners listeners = this.getRunListeners(args);
//如果有监听器监听启动事件,则执行对应的动作
listeners.starting();

 

当前监听是EventPublishingRunListener,starting 方法如下

public void starting() {
    this.initialMulticaster
            .multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}


public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    invokeListener(listener, event);
                }
            });
        }
        else {
            invokeListener(listener, event);
        }
    }
}

 

posted @ 2019-04-05 18:46  webglcn  阅读(1121)  评论(0编辑  收藏  举报