SpringBoot扩展点之一:SpringApplicationRunListener

三种监听器的关系

ApplicationListener、SpringApplicationRunListeners、SpringApplicationRunListener的关系:

  • SpringApplicationRunListeners类和SpringApplicationRunListener类是SpringBoot中新增的类。ApplicationListener是spring中框架的类。
  • 在SpringBoot(SpringApplication类)中,使用SpringApplicationRunListeners、SpringApplicationRunListener来间接调用ApplicationListener。
  • SpringApplicationRunListeners是SpringApplicationRunListener的封装,SpringApplicationRunListeners中包含多个SpringApplicationRunListener,是为了批量执行的封装,SpringApplicationRunListeners与SpringApplicationRunListener生命周期相同,调用每个周期的各个SpringApplicationRunListener。然后广播相应的事件到Spring框架的ApplicationListener。

通过上面的3个特点可以看出SpringApplicationRunListener就是一个ApplicationListener的代理。springboot启动的几个主要过程的监听通知都是通过他来进行回调。

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

}

它定义了5个步骤:

  1.   started(run方法执行的时候立马执行;对应事件的类型是ApplicationStartedEvent):通知监听器,SpringBoot开始执行
  2.   environmentPrepared(ApplicationContext创建之前并且环境信息准备好的时候调用;对应事件的类型是ApplicationEnvironmentPreparedEvent):通知监听器,Environment准备完成
  3.   contextPrepared(ApplicationContext创建好并且在source加载之前调用一次;没有具体的对应事件):通知监听器,ApplicationContext已经创建并初始化完成
  4.   contextLoaded(ApplicationContext创建并加载之后并在refresh之前调用;对应事件的类型是ApplicationPreparedEvent):通知监听器,ApplicationContext已经完成IoC配置价值
  5.   finished(run方法结束之前调用;对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent):通知监听器,SpringBoot启动完成

实现类 EventPublishingRunListener类

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

构造函数

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

    private final SpringApplication application;

    private final String[] args;

    private final SimpleApplicationEventMulticaster initialMulticaster;

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

从上面代码可以看出,它使用了Spring广播器SimpleApplicationEventMulticaster。它把监听的过程封装成了SpringApplicationEvent事件并让内部属性(属性名为multicaster)ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster广播出去,广播出去的事件对象会被SpringApplication中的listeners属性进行处理。

EventPublishingRunListener的initialMulticaster成员变量SimpleApplicationEventMulticaster,以及它的multicastEvent()和invokeListener()方法

initialMulticaster是在构造函数中初始化的,见上面的代码片段。

源码如下:

@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)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        invokeListener(listener, event);
                    }
                });
            }
            else {
                invokeListener(listener, event);
            }
        }
    }

和invokeListener()方法,其参数是ApplicationListener和ApplicationEvent

    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            }
            catch (Throwable err) {
                errorHandler.handleError(err);
            }
        }
        else {
            doInvokeListener(listener, event);
        }
    }

EventPublishingRunListener的5个方法:

首先看下starting方法:

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

ApplicationStartingEvent构造方法中传递了一个SpringApplication对象和args参数。一直传递到了父类EventObject,将SpringApplication对象存放在source变量中。

EventObject类结构。getSource()方法得到的就是SpringApplication对象。

所以说SpringApplicationRunListener和ApplicationListener之间的关系是通过ApplicationEventMulticaster广播出去的SpringApplicationEvent所联系起来的。更多的spring事件知识见《ApplicationEvent事件机制源码分析

如何扩展

对于开发者来说,基本没有什么常见的场景要求我们必须实现一个自定义的SpringApplicationRunListener,即使是SpringBoot中也只默认实现了一个org.springframework.boot.context.eventEventPublishingRunListener, 用来在SpringBoot的整个启动流程中的不同时间点发布不同类型的应用事件(SpringApplicationEvent)。那些对这些应用事件感兴趣的ApplicationListener可以接受并处理(这也解释了为什么在SpringApplication实例化的时候加载了一批ApplicationListener,但在run方法执行的过程中并没有被使用)。

?  如果我们真的在实际场景中自定义实现SpringApplicationRunListener,有一个点需要注意:任何一个SpringApplicationRunListener实现类的构造方法都需要有两个构造参数,一个参数的类型就是我们的org.springframework.boot.SpringApplication,另外一个参数就是args参数列表的String[]:

package com.dxz.controller;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

public class SampleSpringApplicationRunListener implements SpringApplicationRunListener {
    private final SpringApplication application;
    private final String[] args;

    public SampleSpringApplicationRunListener(SpringApplication sa, String[] args) {
        this.application = sa;
        this.args = args;
    }

    @Override
    public void starting() {
        System.out.println("自定义starting");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println("自定义environmentPrepared");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("自定义contextPrepared");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("自定义contextLoaded");
    }

    @Override
    public void finished(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("自定义finished");
    }
}

接着,我们还要满足SpringFactoriesLoader的约定,在当前SpringBoot项目的classpath下新建META-INF目录,并在该目录下新建spring.fatories文件,文件内容如下:

org.springframework.boot.SpringApplicationRunListener=\    com.dxz.SampleSpringApplicationRunListener

原文地址:https://www.cnblogs.com/duanxz/p/11243271.html

时间: 2024-10-08 10:41:42

SpringBoot扩展点之一:SpringApplicationRunListener的相关文章

SpringBoot扩展SpringMVC自动配置

SpringBoot中自动配置了 ViewResolver(视图解析器) ContentNegotiatingViewResolver(组合所有的视图解析器) 自动配置了静态资源文件夹.静态首页.favicon.ico及Webjars Converter(转换器,转换类型使用) Formatter(格式化器) HttpMessageConverter(对SpringMVC的请求和响应进行序列化) MessageCodesResolver(定义错误代码生成规则) ConfigurableWebBi

Springboot中的事件监听类

SpringBoot启动的时候会调用方法SpringApplicationRunListener#contextLoaded,它包含的事件类如下: EventPublishingRunListener 和 自定义的 SpringApplicationRunListener EventPublishingRunListener 发布 ApplicationPreparedEvent 事件 ConfigFileApplicationListener 监听 ApplicationEvent 事件 处理

微服务springboot视频最新SpringBoot2.0.3版本技术视频教程【免费学习】

超火爆的springboot微服务技术怎么学,看这里,springboot超详细的教程↓↓↓↓↓↓https://ke.qq.com/course/179440?tuin=9b386640 01.springboot介绍02.微服务介绍03.springboot第一个例子04.Springboot中的常用注解分析05.springboot启动配置分析06.springboot热部署07.springboot的yaml语法08.springboot属性配置文件方式详解[email protecte

ViewResolver -Springboot中的视图解析器

项目结构如下(Idea) 代码 package com.syu.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver;

Spring(二)核心容器 - 简介 、BeanFactory、ApplicationContext

目录 前言 1.容器简介 2.容器的结构 2.1 BeanFactory 2.2 ApplicationContext 2.2.1 ConfigurableApplicationContext 2.2.2 WebApplicationContext 2.3 差异对比 3.ApplicationContext 准备启动 4.总结 前言 在上篇文章中,和大家一起讨论了 Spring 的整体架构,其大致分为五个模块:核心容器.AOP.Web.Data 数据访问.Test模块.其中核心容器是 Sprin

springboot线程池的使用和扩展

我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本文地址:http://blog.csdn.net/boling_cavalry/article/details/79120268 实战环境 windowns10: jdk1.8: springboot 1.5.9.RELEASE: 开发工具:IntelliJ IDEA: 实战源码 本次实战的源码可以

SpringBoot日记——SpringMvc自动配置与扩展篇

为了让SpringBoot保持对SpringMVC的全面支持和扩展,而且还要维持SpringBoot不写xml配置的优势,我们需要添加一些简单的配置类即可实现: 通常我们使用的最多的注解是: @Bean @Component 配置后的类就是我们要写在容器中的一些配置:详情后续再说,或者你也可以参考官方文档 关于扩展 这里我们说一下如何做扩展呢,先看一下原先在SpringMvc中我们是如何写的,来看XML(这是一段关于路径映射和拦截器的简单配置,访问hello路径也展示success.html的页

Springboot对SpringMVC如何扩展配置

原文地址:http://www.javayihao.top/detail/171 概述 Springboot在web层的开发基本都是采用Springmvc框架技术,但是Springmvc中的某些配置在boot是没有的,我们就应该根据自己的需求进行对mvc扩展配置 Springboot1.x版本如何配置 通过注解@Configuration一个类,继承webmvcconfigureradapter,然后根据需求实现里面的方法. Springboot2.x版本如何配置 通过实现webmvcconfi

springboot开发之扩展springmvc

可以在Java定义自己配置的springmvc: MyMvcConfig.java package com.gong.springbootcurd.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotatio