ApplicationListener、SpringApplicationRunListeners、SpringApplicationRunListener的关系:html
经过上面的3个特色能够看出SpringApplicationRunListener就是一个ApplicationListener的代理。springboot启动的几个主要过程的监听通知都是经过他来进行回调。spring
从命名咱们就能够知道它是一个监听者,那纵观整个启动流程咱们会发现,它实际上是用来在整个启动流程中接收不一样执行点事件通知的监听者,SpringApplicationRunListener接口规定了SpringBoot的生命周期,在各个生命周期广播相应的事件,调用实际的ApplicationListener类。springboot
源码以下:app
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个步骤:框架
EventPublishingRunListener类 实现了SpringApplicationRunListener,它具备广播事件的功能。ide
构造函数函数
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属性进行处理。源码分析
initialMulticaster是在构造函数中初始化的,见上面的代码片断。post
源码以下:this
@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); } }
首先看下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