首页 > 编程语言 >springboot源码剖析(二) 事件发布

springboot源码剖析(二) 事件发布

时间:2022-10-30 15:11:33浏览次数:44  
标签:listener springboot eventType 剖析 源码 事件 监听器 null retriever

  概念

           springboot在启动流程中会发布一些事件通知依赖组件进行主动更新。

           原理是springboot使用到的一种设计模式: 观察者模式。优点是解耦合启动流程,增加了spring的扩展性。


  实现原理

     被观察者会维护一个事件发布器,事件发布器会注册持有监听者(观察者)的引用。

          当被观察者发生状态改变,事件发布器会广播给所有对该事件感兴趣的监听者,之后监听者会执行对应的事件触发方法。

   uml类图

     事件发布流程


       源码剖析

           事件发布触发

/** springApplication.class 事件发布 */
public ConfigurableApplicationContext run(String... args) {
     ...
     // 扫描META-INF/spring-factories 中的org.springframework.boot.SpringApplicationRunListener,构造事件发布器
     SpringApplicationRunListeners listeners = this.getRunListeners(args);
     // ★ 给关注ApplicationStartingEvent事件的listenter发布消息
     listeners.starting();
     ...
 }

/** EventPublishingRunListener.class 事件发布器 */
// 构造方法(实现的观察者模式:由被观察者维护监听者并广播消息)
public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    // ★ 实例化一个广播器
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    Iterator var3 = application.getListeners().iterator();
    // ★ 把springapplication类的监听器都注册到广播器中
    while(var3.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var3.next();
        this.initialMulticaster.addApplicationListener(listener);
    }
}
// 发布ApplicationStartingEvent事件
public void starting() {
    // 广播事件
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}

              广播事件

/** SimpleApplicationEventMulticaster.class 广播器 */
// 广播事件
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    // 多线程执行监听器更新
    Executor executor = this.getTaskExecutor();
    // 1.获取需要更新的监听器
    Iterator var5 = this.getApplicationListeners(event, type).iterator();

    // 2.执行监听器的更新
    while(var5.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {
                this.invokeListener(listener, event);
            });
        } else {
            // 最底层其实就是执行listener实现的onApplicationEvent(event)方法
            this.invokeListener(listener, event);
        }
    }
}
// 1.获取监听器
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
    // sprinApplication对象和类
    Object source = event.getSource();
    Class<?> sourceType = source != null ? source.getClass() : null;
    // cacheKey记录当前事件和事件类型
    AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
    // retriever记录对应事件需要更新的监听器
    AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        return retriever.getApplicationListeners();
    } else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) {
        synchronized(this.retrievalMutex) {
            retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
            if (retriever != null) {
                return retriever.getApplicationListeners();
            } else {
                retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
                // 1.1 筛选对事件感兴趣的监听者
                Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
                this.retrieverCache.put(cacheKey, retriever);
                return listeners;
            }
        }
    } else {
        return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
    }
}
// 1.1 筛选监听者
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
    List<ApplicationListener<?>> allListeners = new ArrayList();
    LinkedHashSet listeners;
    LinkedHashSet listenerBeans;
    // 监听器数组
    synchronized(this.retrievalMutex) {
        listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
    }

    Iterator var7 = listeners.iterator();
    // 1.1.1 感兴趣的放入retriever数组中
    while(var7.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var7.next();
        if (this.supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                retriever.applicationListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }

    // 我运行的时候没有走到,多加了单例相关的判断
    if (!listenerBeans.isEmpty()) {
        /* ... */
    }

    // 排序,更新retriever的监听者
    AnnotationAwareOrderComparator.sort(allListeners);
    if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
        retriever.applicationListeners.clear();
        retriever.applicationListeners.addAll(allListeners);
    }    

    return allListeners;
}
// 1.1.1 监听器是否对事件感兴趣
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    // 转成通用监听类型
    GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
    // 看监听器自己实现的supportsEventType和supportsSourceType方法是否对该事件感兴趣
    return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
}

           

标签:listener,springboot,eventType,剖析,源码,事件,监听器,null,retriever
From: https://www.cnblogs.com/Duikerdd/p/16841343.html

相关文章

  • Spring源码-context:component-scan解析
    调用AbstractApplicationContext.refresh()刷新容器,会调用obtainFreshBeanFactory()获取ConfigurableListableBeanFactory。会去调用loadBeanDefinitions()方法解析xml文件......
  • springboot源码剖析(一) 总体启动流程
    前言  之前阅读STL(C++)源码的时候,有所感悟:大佬的代码总会实践到部分设计模式、新型语法特性,亦或是精巧的算法和数据结构。     读源码的技巧:大......
  • Spring源码分析之AOP
    AOP是什么面向切面的程序设计(Aspect-orientedprogramming,AOP,又译作面向方面的程序设计、剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进......
  • SpringMVC源码-DispatcherServlet初始化
    web容器启动后会实例化Servlet,会执行Servlet的init方法且只会执行一次。后续调用doService处理客户请求。DispatcherServlet的构造方法publicDispatcherServlet(){ su......
  • 第四章 SpringBoot 底层机制
    搭建SpringBoot底层机制开发环境1、创建Maven项目lzw-springboot2、导入相关依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.o......
  • Springboot centos7 启动
     1、java-jardemo.jar说明:用这种方法启动后,不能继续执行其它命令了,如果想要继续执行其它命令,就都打断,打断一般用ctrl+c。2、java-jardemo.jar&第2种在第1种方式的基础......
  • redisson分布式限流[RRateLimiter]源码分析
    接下来在讲一讲平时用的比较多的限流模块--RRateLimiter1.简单使用publicstaticvoidmain(String[]args)throwsInterruptedException{RRateLimiterrateLimit......
  • SpringBoot3.x原生镜像-Native Image尝鲜
    前提Spring团队致力于为Spring应用程序提供原生映像支持已经有一段时间了。在SpringBoo2.x的SpringNative实验项目中酝酿了3年多之后,随着SpringFramework6和SpringBoo......
  • 多语言在线客服系统源码-自动识别中英环境-私有化部署完美支持跨境电商网站
    如果您的客户遍布全球,客户沟通就必须跨越语言障碍。用客户当地的语言跟他们交谈,可以帮助您在客户生命周期的所有阶段建立信任,当然也包括服务支持。 具体做法,看看这四点......
  • SpringBoot(三) - Ribbon客户端负载均衡,Zuul网关,Config配置中心
    1、Ribbon客户端负载均衡1.1依赖1.2配置信息#feign默认加载了ribbon负载均衡,默认负载均衡机制是:轮询#负载均衡机制是添加在消费端(客户端)的,如果改为随机,指定服务名......