【深入SpringBoot 第三章】SpringApplicationRunListener及其周期

原创 2016年06月01日 14:24:07

一 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<ApplicationStartedEvent> {
    @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://blog.csdn.net/u011179993 】

Spring ApplicationListener使用方法及问题

使用场景在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进...

spring boot实战(第二篇)事件监听

spring boot 实战 2.事件监听前言spring boot在启动过程中增加事件监听机制,为用户功能拓展提供极大的便利。支持的事件类型四种 ApplicationStartedEvent ...

Spring Boot【原理分析】(1)——SpringApplication

SpringApplication作为Spring Boot的启动类。 一、入口方法run public static ConfigurableApplicationContext run...
  • wwmfeng
  • wwmfeng
  • 2016年12月05日 11:04
  • 1642

Spring boot源码分析-ApplicationListener应用环境(5)

Spring boot源码分析-ApplicationListener应用环境(5)关于ApplicationListenerApplicationListener为spring框架内的事件监听接口,...
  • jamet
  • jamet
  • 2017年09月20日 16:36
  • 244

Spring 服务启动 自动执行(ApplicationListener)

适合Spring 容器 启动后 初始化 数据

【深入SpringBoot 1.3.5 第一章】Boot应用的启动流程

一、 快速创建一个Boot应用使用maven org.springframework.boot spring-boot-starter-parent 1.3.5.RELEASE...

spring boot应用启动原理分析

spring boot quick start在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web...

Spring Boot 特性 —— SpringApplication

通过前面的学习,我们了解了如何构建一个 Spring Boot 应用以及 Spring Boot 项目的基本配置,这里我们将逐步细化到每个具体的功能模块来了解 Spring Boot 的特性。...
  • cqdzdj
  • cqdzdj
  • 2016年10月24日 11:49
  • 7651

@SpringBootApplication的使用

之前用户使用的是3个注解注解他们的main类。分别是@Configuration,@EnableAutoConfiguration,@ComponentScan。由于这些注解一般都是一起使用,spri...

Spring Boot的SpringApplication类详解

相信使用过Spring Boot的开发人员,都对Spring Boot的核心模块中提供的SpringApplication类不陌生。SpringApplication类的run()方法往往在Sprin...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【深入SpringBoot 第三章】SpringApplicationRunListener及其周期
举报原因:
原因补充:

(最多只允许输入30个字)