listeners.starting()

简介: listeners.starting()

SpringBoot启动流程之(listener.starting())

  • starting()流程图:

根据前面讲的SpringApplicationRunListeners listeners = getRunListeners(args);我们已经把所有事件都交给了广播

继续往后看,在系统获取完SpringApplicationRunListeners之后,紧接着便执行了starting方法,代码如下

     

SpringApplicationRunListeners listeners=getRunListeners(args);
        //SpringApplicationRunListeners执行了start方法
        listeners.starting();

遍历SpringApplicationRunListeners的listener集合

class SpringApplicationRunListeners {
    private final Log log;
    //这里接受了一个以SpringApplicationRunListener为类型的List集合
    private final List<SpringApplicationRunListener> listeners;
    //SpringApplicationRunListeners的默认构造,接受了一个子类型继承SpringApplicationRunListener的List
    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList<>(listeners);
    }
    //遍历listener集合
    void starting() {
        for (SpringApplicationRunListener listener : this.listeners) {
            //启动listener,分派给SpringApplicationRunListener的具体实现EventPublishingRunListener
            listener.starting();
        }
    }
//下面还有很多方法,省略了。。。。。。逻辑基本上跟starting一样
  • SpringApplicationRunListeners参数细节:
  • 在start阶段,this.listeners只有一个为EventPublishingRunListener参数
  • EventPublishingRunListener内部建立了广播SimpleApplicationEventMulticaster
  • 广播内部拥有SpringApplication在构造的所有listener事件

来看看SpringApplicationRunListener的内部结构

public interface SpringApplicationRunListener {
    //run方法第一次启动时调用它
    default void starting() {
    }
    //在环境建立好的时候调用它(建立environment对象)
    default void environmentPrepared(ConfigurableEnvironment environment) {
    }
    //建立ApplicationContext但是不引入配置信息
    default void contextPrepared(ConfigurableApplicationContext context) {
    }
    //载入配置信息
    default void contextLoaded(ConfigurableApplicationContext context) {
    }
    default void started(ConfigurableApplicationContext context) {
    }
    default void running(ConfigurableApplicationContext context) {
    }
    default void failed(ConfigurableApplicationContext context, Throwable exception) {
    }
}
  • 来看看EventPublishingRunListener类吧
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    private final SpringApplication application;
    private final String[] args;
    private final SimpleApplicationEventMulticaster initialMulticaster;
    /**
     * application是new SpringApplication()时的构造方法的application,这里遍历的application.getListeners()就是构造
     * 时读取以ApplicationListener.class为条件的META-INF/spring.factories的全限定类名集合
     * @param application
     * @param args
     */
    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        for (ApplicationListener<?> listener : application.getListeners()) {
            //将listener添加到this.defaultRetriever.applicationListeners里面,每一个listener内部进行了去重,防止相同事件的调用
            this.initialMulticaster.addApplicationListener(listener);
        }
    }
    // 这个地方后面会说,其实从这里开始才是真正的开始启动listener
    public void starting() {
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
    //下面还有很多方法,基本上跟starting差不多
}
  • 同样查看starting()方法,发现EventPublishingRunListener将所有事件委托给了SimpleApplicationEventMulticaster(事件多播实现类)
  • 到此为止,事件的start的调用链路是理清了,看看它们之间的关系
  • 总结
  1. 由SpringApplication创建SpringApplicationRunListeners,并且把经过构造的SpringApplication作为参数传递给了EventPublishingRunListener
  2. SpringApplicationRunListeners包含了SpringApplicationRunListener的list集合
  3. SpringApplicationRunListener的具体实现由EventPublishingRunListener实现
  4. EventPublishingRunListener最终把所有listener委托给了SimpleApplicationEventMulticaster实现
  5. 其实SpringApplicationRunListeners listeners = getRunListeners(args) ;阶段就是把SpringApplication构造阶段的listener交给了广播,为随后的start打下基础
  • 事件由SimpleApplicationEventMulticaster多播器实现
public void multicastEvent(final ApplicationEvent event,@Nullable ResolvableType eventType){
        //获取event的具体分派类型
        ResolvableType type=(eventType!=null?eventType:resolveDefaultEventType(event));
        Executor executor=getTaskExecutor();
        //getApplicationListeners(event,type)会根据ResolvableType过滤我们需要的listener。接下来会讲
        //遍历所有listener,并且把listener全部start
        for(ApplicationListener<?> listener:getApplicationListeners(event,type)){
        //是否存在线程池支持异步执行
        if(executor!=null){
        executor.execute(()->invokeListener(listener,event));
        }
        else{
        //同步执行listener事件()
        invokeListener(listener,event);
        }
        }
        }
//不重要
protected void invokeListener(ApplicationListener<?> listener,ApplicationEvent event){
        ......省略
        doInvokeListener(listener,event);
        ......省略
        }
//最终执行的是这个
private void doInvokeListener(ApplicationListener listener,ApplicationEvent event){
        //所有的listener最终都是基于这个调用的,接下来看看onApplicationEvent(event);的庐山真面目
        listener.onApplicationEvent(event);
//省略......
  • 根据ResolvableType过滤listeners
  • 未过滤时的listeners
protected boolean supportsEvent(
        //根据当前listener类型加载不同的GenericApplicationListener实现
        ApplicationListener<?> listener,ResolvableType eventType,@Nullable Class<?> sourceType){
        //为listener配置GenericApplicationListener接口的具体实现
        //如果当前listener与GenericApplicationListener存在关联,则类型转化为GenericApplicationListener
        //否则定义适配器GenericApplicationListenerAdapter为两者不兼容接口提供兼容
        GenericApplicationListener smartListener=(listener instanceof GenericApplicationListener?
        (GenericApplicationListener)listener:new GenericApplicationListenerAdapter(listener));
        //这两个方法则是进行具体的listener检测
        return(smartListener.supportsEventType(eventType)&&smartListener.supportsSourceType(sourceType));
        }
  • 这是过滤后的listener
  • (事件的真正执行)ApplicationListener#onApplicationEvent()
  • 过滤的规则
//通过非适配器的过滤规则,这是Class自带的isAssignableFrom方法,用于确定type是否可以转换为supportedType
private boolean isAssignableFrom(Class<?> type,Class<?>...supportedTypes){
        if(type!=null){
        for(Class<?> supportedType:supportedTypes){
        if(supportedType.isAssignableFrom(type)){
        return true;
        }
        }
        }
        return false;
        }
//通过适配器的过滤规则则是通过ResolvableType.isAssignableFrom()方法或者通过
//ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric();来实现
//ResolvableType的过滤规则则是确定该类型能否在对象树上找到对应的指定对象
  • 无论是通过Class、ResolvableType来实现过滤,其本质上都是在确定一个类型是否与指定类型存在关联(比如说继承、实现......)
  • listeners的具体执行listener.onApplicationEvent(event);
/**
 * 由应用程序事件监听器实现的接口。基于 Observer 设计模式的标准 java.util.EventListener 接口。
 * 从 Spring 3.0 开始,ApplicationListener 可以一般性地声明它感兴趣的事件类型。
 * 当向 Spring ApplicationContext 注册时,事件将被相应地过滤,只有匹配事件对象才会调用侦听器。
 * @param <E>
 */
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    //现在就是正真的开始start了,对于所有该接口的实现类,
    // 都可以在运行时根据具体创建类型执行onApplicationEvent,拓展性十分棒哦
    void onApplicationEvent(E event);
}
-PS:过滤后执行的四个listener
        -LoggingApplicationListener(引导系统日志)
        -BackgroundPreinitializer(ApplicationListener 在耗时任务的后台线程中触发早期初始化)
        -LiquibaseServiceLocatorApplicationListener(说啥换版本?但是不晓得啥意思)
        -DelegatingApplicationListener(context.listener.classes下的listeners,不理解)
目录
相关文章
|
10月前
|
应用服务中间件
Tomcat报错:The required Server component failed to start so Tomcat is unable to start
Tomcat报错:The required Server component failed to start so Tomcat is unable to start
207 0
|
4月前
|
负载均衡 Java 应用服务中间件
Client not connected, current status:STARTING
Client not connected, current status:STARTING
443 1
|
安全 Ubuntu 测试技术
l4re Getting started
l4re Getting started
304 0
|
Oracle 关系型数据库 Linux
[20170705]lsnrctl status LISTENER_SCAN1
[20170705]lsnrctl status LISTENER_SCAN1.txt --//前几天在解决问题时遇到的问题,现在分析看看.当时没注意操作用户名,选择错误的用户执行(oracle用户执行).
1516 0
|
Java Apache Spring
Exception sending context initialized event to listener instance of class
详细错误信息如下: 严重: Exception sending context initialized event to listener instance of class com.auth.spring.
1208 0
Veloce 之 Getting Started
Veloce 之所以能够加速仿真,原因是Veloce把DUT(Design Under Test) 和 TB(TestBench) 一起综合成实际的电路,然后下载到Veloce硬件中,在硬件上跑,所以是比软件仿真快得多。 那么怎样才能把Veloce用起来,让它来加速我们的仿真呢?
Veloce 之 Getting Started
|
Ruby Web App开发
|
SQL Oracle 关系型数据库
ORA-12514, TNS:listener does not currently know of service requested in connect descriptor案例2
今天使用SQL Developer连接一台测试服务器数据库(ORACLE 11g)时,遇到了“ORA-12514, TNS:listener does not currently know of service requested in connect descriptor”错误,具体提示如下所示:...
5354 0
|
数据库
ORA-12520: TNS:listener could not find available handler for requested type of server
当你碰到ORA-12520错误时,如下所示: 英文错误提示: ORA-12520: TNS:listener could not find available handler for requested type of server 中文错误提示: ORA-12520: TNS: 监听程序无法为请求的服务器类型找到可用的处理程序 一般你应该从下面两个方面去检查出错原因并解决问题:   1:数据库是专用服务器,但是在tnsname.ora配置文件中设置的连接方式是shared,这种情况需要修改tnsname.ora配置文件,这种错误情况一般发生在第一次连接数据库服务器。
1387 0
|
JavaScript Linux 前端开发