博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【深入SpringBoot 第三章】SpringApplicationRunListener及其周期
阅读量:4290 次
发布时间:2019-05-27

本文共 5952 字,大约阅读时间需要 19 分钟。

一 SpringApplicationRunListener 类

三种监听器的关系

SpringApplicationRunListeners类和SpringApplicationRunListener类是SpringBoot中新增的类。SpringApplication类 中使用它们来间接调用ApplicationListener

SpringApplicationRunListeners包含了多个SpringApplicationRunListener。

SpringApplicationRunListener介绍

SpringApplicationRunListener接口规定了SpringBoot的生命周期,在各个生命周期广播相应的事件,调用实际的ApplicationListener类。

接口定义如下:

public interface SpringApplicationRunListener {     //刚执行run方法时    void started();     //环境建立好时候    void environmentPrepared(ConfigurableEnvironment environment);     //上下文建立好的时候    void contextPrepared(ConfigurableApplicationContext context);    //上下文载入配置时候    void contextLoaded(ConfigurableApplicationContext context);    //上下文刷新完成后,run方法执行完之前    void finished(ConfigurableApplicationContext context, Throwable exception);}

SpringApplication类实际使用的是SpringApplicationRunListeners类,它可以包含多个SpringApplicationRunListener实例,与SpringApplicationRunListener生命周期相同,调用每个周期的各个SpringApplicationRunListener。然后广播相应的事件到ApplicationListener

实现类 EventPublishingRunListener类

EventPublishingRunListener类 实现了SpringApplicationRunListener,它具有广播事件的功能。

构造函数

从下面代码可以看出,它使用了Spring广播器SimpleApplicationEventMulticaster

public EventPublishingRunListener(SpringApplication application, String[] args) {        this.application = application;        this.args = args;        //新建立广播器        this.multicaster = new SimpleApplicationEventMulticaster();        for (ApplicationListener
listener : application.getListeners()) { this.multicaster.addApplicationListener(listener); } }

* 当上下文准备好时候,注册名为“applicationEventMulticaster”的bean*

@Override    public void contextPrepared(ConfigurableApplicationContext context) {        registerApplicationEventMulticaster(context);    }    private void registerApplicationEventMulticaster(            ConfigurableApplicationContext context) {        context.getBeanFactory().registerSingleton(                AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,                this.multicaster);        if (this.multicaster instanceof BeanFactoryAware) {            ((BeanFactoryAware) this.multicaster)                    .setBeanFactory(context.getBeanFactory());        }    }

把SpringApplication对象中暂存的所有监听器交给相应的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)); }

拓展:SpringContext如何的到监听器???

当使用SpringApplication#createAndRefreshContext(..)中refresh(context)时,
在AbstractApplicationContext类 中,有如下方法:

protected void initApplicationEventMulticaster() {        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();        if(beanFactory.containsLocalBean("applicationEventMulticaster")) {            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);            if(this.logger.isDebugEnabled()) {                this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");            }        } else {            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);            if(this.logger.isDebugEnabled()) {                this.logger.debug("Unable to locate ApplicationEventMulticaster with name \'applicationEventMulticaster\': using default [" + this.applicationEventMulticaster + "]");            }        }    }

可以看出,前面注册了名为“applicationEventMulticaster”的bean,所以SpringContext不会创建另外的广播器,而是使用我们在EventPublishingRunListener建立的。

EventPublishingRunListener类生命周期对应的事件

从它的源码中可以看出

started()—>ApplicationStartedEvent事件类

environmentPrepared(Environment e)—>ApplicationEnvironmentPreparedEvent事件类

contextPrepared(ApplicationContext c)–>在context中注册广播器bean

contextLoaded(ApplicationContext c)–>ApplicationPreparedEvent事件

finished(ApplicationContext context, Throwable t) –>ApplicationFailedEvent()和ApplicationReadyEvent()事件

二 在Boot中自定义SpringApplicationRunListener和ApplicationListener

自定义SpringApplicationRunListener(不推荐)

SpringApplication类没有直接添加SpringApplicationRunListener的方法。查看源码可知, 可以在spring.factory中定义org.springframework.boot.SpringApplicationRunListener=xxx,就会被初始化(与在第一章中初始化函数中相同)。

自己实现的类必须含有以下构造函数,才能被Boot调用

public MyRunListener(SpringApplication application, String[] args) { }

META-INF/spring.factory

org.springframework.boot.SpringApplicationRunListener=\com.jazz.other.MyRunListener

自定义ApplicationListener

* 方法一:代码中添加*

使用SpringApplication#setListeners方法添加监听器SpringApplication#setListeners(..[])或者addListeners(..)

使用泛型构造专门接收ApplicationStartedEvent事件的监听器

public class MyStartListner implements ApplicationListener
{
@Override public void onApplicationEvent(ApplicationStartedEvent event) { System.out.println("我的程序启动啦!!!"); }}

主程序

public static void main(String[] args) {        SpringApplication application = new SpringApplication(App.class);        application.addListeners(new MyStartListner());        application.run(args);   }

屏幕输出:

我的程序启动啦!!!

. _ _ _
/\ / _ ()_ _ _ _ \ \ \ \
( ( )___ | ‘_ | ‘| | ‘ \/ _` | \ \ \ \
\/ _)| |)| | | | | || (| | ) ) ) )
’ |_| .|| ||| |_, | / / / /
=========||==============|__/=///_/
:: Spring Boot :: (v1.3.5.RELEASE)

2016-05-26 21:25:23.998 INFO 5008 — [ main] App : Starting App > on Jiazhi-PC with PID 5008 (E:\IdeaProjects\test\target\classes started by Jiazhi in > > E:\IdeaProjects\test)

2016-05-26 21:25:24.000 INFO 5008 — [ …….//省略

方法二:文件中添加

根目录下建立 META-INF/spring.factory,添加自定义的监听器到org.springframework.context.ApplicationListener键

转载地址:http://eihgi.baihongyu.com/

你可能感兴趣的文章
CAS原子操作实现无锁及性能分析
查看>>
Linux 互斥锁、原子操作实现原理
查看>>
搭建简单hls直播测试服务
查看>>
共享内存的数据同步
查看>>
Cache和Buffer的区别
查看>>
50个sql语句
查看>>
MYSQL sql 语句性能分析
查看>>
C++操作Redis数据库
查看>>
python yield用法
查看>>
python pipe模块用法
查看>>
安装完 MySQL 后必须调整的 10 项配置
查看>>
开发者必备的 12 个 JavaScript 库
查看>>
http错误码
查看>>
python 多线程
查看>>
sipp命令 各参数含义
查看>>
搜集的动植物分类、检索网站
查看>>
ffmpeg源码分析之媒体打开过程
查看>>
Ubuntu/centos/redhat/SUSE sipp安装(带rtp支持,3.5.1版本)
查看>>
周鸿祎:很多程序员聪明,但我一看就知道他不会成功
查看>>
编译程序遇到问题 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object;
查看>>