SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

栏目: Java · 发布时间: 5年前

微信公众号:吉姆餐厅ak 学习更多源码知识,欢迎关注。

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

SpringBoot2 | SpringBoot启动流程源码分析(一)

SpringBoot2 | SpringBoot启动流程源码分析(二)

SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三)

SpringBoot2 | SpringBoot Environment源码分析(四)

SpringBoot2 | SpringBoot自定义AutoConfiguration | SpringBoot自定义starter(五)

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

SpringBoot2 | 条件注解@ConditionalOnBean原理源码深度解析(七)

SpringBoot2 | Spring AOP 原理源码深度剖析(八)

SpringBoot2 | SpingBoot FilterRegistrationBean 注册组件 | FilterChain 责任链源码分析(九)

SpringBoot2 | BeanDefinition 注册核心类 ImportBeanDefinitionRegistrar (十)

SpringBoot2 | Spring 核心扩展接口 | 核心扩展方法总结(十一)

概述

我们都知道Spring源码博大精深,阅读起来相对困难。原因之一就是内部用了大量的监听器,spring相关的框架,皆是如此, spring security,springBoot 等。今天来看下 springBoot 监听器的应用。

因为springBoot是对spring的封装,所以springBoot的监听器的应用主要是在启动模块。

源码

springBoot 监听器的主要分为两类:

1)运行时监听器

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
复制代码

2)上下文监听器

# Application Listeners
org.springframework.context.ApplicationListener=\
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.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
复制代码

注意:springBoot运行时监听器作用是用来触发springBoot上下文监听器,再根据各监听器监听的事件进行区分。上面默认监听器的作用如下:

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

运行时监听器和上下文监听器都是定义在 spring.factories 文件中。

监听器触发

启动流程前面两篇已经有详细分析,所以本篇我们只看监听器相关逻辑。

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        //获取启动监听器的监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
        //用该监听器来启动所有监听器
        listeners.started();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            context = createAndRefreshContext(listeners, applicationArguments);
            afterRefresh(context, applicationArguments);
            listeners.finished(context, null);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            return context;
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, ex);
            throw new IllegalStateException(ex);
        }
    }
复制代码

SpringApplicationRunListeners listeners = getRunListeners(args); 这里创建了一个关键类: SpringApplicationRunListeners

SpringApplicationRunListeners

这是一个封装 工具 类,封装了所有的启动类监听器。默认只有一个实例,这里封装成 List<SpringApplicationRunListener> listeners ,主要是方便我们扩展,我们可以定义自己的启动类监听器。

//启动类监听器
    private final List<SpringApplicationRunListener> listeners;

    SpringApplicationRunListeners(Log log,
            Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList<SpringApplicationRunListener>(listeners);
    }

	//启动上下文事件监听
    public void started() {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.started();
        }
    }

	//environment准备完毕事件监听
    public void environmentPrepared(ConfigurableEnvironment environment) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.environmentPrepared(environment);
        }
    }

    //spring上下文准备完毕事件监听
    public void contextPrepared(ConfigurableApplicationContext context) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.contextPrepared(context);
        }
    }

	//上下文配置类加载事件监听
    public void contextLoaded(ConfigurableApplicationContext context) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.contextLoaded(context);
        }
    }

	//上下文构造完成事件监听
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
        for (SpringApplicationRunListener listener : this.listeners) {
            callFinishedListener(listener, context, exception);
        }
    }
复制代码

在前面的启动流程源码分析中介绍过,这些方法会在合适的时间点触发执行,然后广播出不同的事件。

跟进去 EventPublishingRunListener :

public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        //spring事件机制通用的事件发布类
        this.multicaster = new SimpleApplicationEventMulticaster();
        for (ApplicationListener<?> listener : application.getListeners()) {
            this.multicaster.addApplicationListener(listener);
        }
    }
复制代码

上面会默认创建全局的事件发布工具类 SimpleApplicationEventMulticaster

@Override
    public void started() {
        publishEvent(new ApplicationStartedEvent(this.application, this.args));
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        publishEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args,
                environment));
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        registerApplicationEventMulticaster(context);
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        for (ApplicationListener<?> listener : this.application.getListeners()) {
            if (listener instanceof ApplicationContextAware) {
                ((ApplicationContextAware) listener).setApplicationContext(context);
            }
            context.addApplicationListener(listener);
        }
        publishEvent(new ApplicationPreparedEvent(this.application, this.args, context));
    }

    @Override
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
        publishEvent(getFinishedEvent(context, exception));
    }
复制代码

可以看出每个方法都会发布不同的事件,所有的事件统一继承 SpringApplicationEvent

事件广播

继续跟进事件广播方法:

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

    @Override
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //根据事件类型选取需要通知的监听器
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            //获取线程池,如果为null,则同步执行
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        invokeListener(listener, event);
                    }
                });
            }
            else {
                invokeListener(listener, event);
            }
        }
    }
复制代码

重点来看一下根据类型获取监听器: getApplicationListeners(event, type) 跟进该方法:

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
            ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {

        //......
        //根据类型匹配监听器
        for (ApplicationListener<?> listener : listeners) {
            if (supportsEvent(listener, eventType, sourceType)) {
                if (retriever != null) {
                    retriever.applicationListeners.add(listener);
                }
                allListeners.add(listener);
            }
        }
        //......
        AnnotationAwareOrderComparator.sort(allListeners);
        return allListeners;
    }
复制代码

上面省去了一些不相关代码,继续跟进: supportsEvent(listener, eventType, sourceType)

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
        //判断监听器是否是 GenericApplicationListener 的子类,如果不是就返回一个GenericApplicationListenerAdapter
        GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
                (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
        return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
    }
复制代码
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

    boolean supportsEventType(ResolvableType eventType);
    boolean supportsSourceType(Class<?> sourceType);
}
复制代码

这里又出现一个关键类: GenericApplicationListener ,该类是 spring 提供的用于重写匹配监听器事件的接口。 就是说如果需要判断的监听器是 GenericApplicationListener 的子类,说明类型匹配方法已被重现,就调用子类的匹配方法。如果不是,则为我们提供一个默认的适配器用来匹配: GenericApplicationListenerAdapter

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

继续跟进该类的 supportsEventType(ResolvableType eventType) 方法:

public boolean supportsEventType(ResolvableType eventType) {
        if (this.delegate instanceof SmartApplicationListener) {
            Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.getRawClass();
            return ((SmartApplicationListener) this.delegate).supportsEventType(eventClass);
        }
        else {
            return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
        }
    }
复制代码

可以看到该类最终调用的是 declaredEventType.isAssignableFrom(eventType) 方法,也就是说,如果我们没有重写监听器匹配方法,那么发布的事件 event 会被监听 event以及监听event的父类的监听器监听到。

自定义监听器

/**
 * Created by zhangshukang on 2018/9/22.
 */
public class SimpleApplicationListener implements GenericApplicationListener,ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("myApplistener execute...");
    }

    @Override
    public boolean supportsEventType(ResolvableType eventType) {
        return true;
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return true;
    }

    @Override
    public int getOrder() {
        return 0;
    }
复制代码

上面 supportsEventTypesupportsSourceType 是预留的扩展方法,这里全部为true,也就意味着监听所有的 ApplicationEvent 事件,方法会执行多次:

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

以上所述就是小编给大家介绍的《SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Bandit Algorithms for Website Optimization

Bandit Algorithms for Website Optimization

John Myles White / O'Reilly Media / 2013-1-3 / USD 19.99

This book shows you how to run experiments on your website using A/B testing - and then takes you a huge step further by introducing you to bandit algorithms for website optimization. Author John Myle......一起来看看 《Bandit Algorithms for Website Optimization》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具