当前位置: 首页 > news >正文

EventListener原理

目录

  • 目录
  • 流程
  • initApplicationEventMulticaster()
  • registerListeners()
  • finishRefresh()
  • publishEvent()
  • @EventListener处理

流程

容器的刷新流程如下:

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }
      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

其中与EventListener有关联的步骤

  • initApplicationEventMulticaster(); 初始化事件多播器
  • registerListeners(); 注册Listener到多播器
  • finishBeanFactoryInitialization(beanFactory); 涉及将@EventListener转为普通Listener
  • finishRefresh(); 发布容器刷新完成事件ContextRefreshedEvent

initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //找applicationEventMulticaster的组件
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
     this.applicationEventMulticaster =
           beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
     if (logger.isDebugEnabled()) {
        logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
     }
   }
   else {
     //没有就创建一个
     this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
     //注册到beanFactory
     beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
     if (logger.isDebugEnabled()) {
        logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
              APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
              "': using default [" + this.applicationEventMulticaster + "]");
     }
   }
}

registerListeners()

protected void registerListeners() {
   // Register statically specified listeners first.
   for (ApplicationListener<?> listener : getApplicationListeners()) {
     getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let post-processors apply to them!
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
     getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // Publish early application events now that we finally have a multicaster...
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
     for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
        getApplicationEventMulticaster().multicastEvent(earlyEvent);
     }
   }
}

finishRefresh()

protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   //发布事件
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

publishEvent() 发布事件,我们也可以手动调用容器的publishEvent() 方法来发布事件

ApplicationContext.publishEvent(new MyEvent("test"));

publishEvent()

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   // Decorate event as an ApplicationEvent if necessary
   ApplicationEvent applicationEvent;
   if (event instanceof ApplicationEvent) {
     applicationEvent = (ApplicationEvent) event;
   }
   else {
     applicationEvent = new PayloadApplicationEvent<>(this, event);
     if (eventType == null) {
        eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
     }
   }

   // Multicast right now if possible - or lazily once the multicaster is initialized
   if (this.earlyApplicationEvents != null) {
     this.earlyApplicationEvents.add(applicationEvent);
   }
   else {
     //获取多播器
     getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
   }

   // Publish event via parent context as well...
    //父容器发布事件
   if (this.parent != null) {
     if (this.parent instanceof AbstractApplicationContext) {
        ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
     }
     else {
        this.parent.publishEvent(event);
     }
   }
}

@EventListener处理

原理:通过EventListenerMethodProcessor来处理@Eventlstener

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware 

EventListenerMethodProcessor 是一个 SmartInitializingSingleton。

SmartInitializingSingleton什么时候执行呢?

在Refresh()

​ -> finishBeanFactoryInitialization(beanFactory);

​ -> DefaultListableBeanFactory#preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
     RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
     if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
           Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
           if (bean instanceof FactoryBean) {
              final FactoryBean<?> factory = (FactoryBean<?>) bean;
              boolean isEagerInit;
              if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                           ((SmartFactoryBean<?>) factory)::isEagerInit,
                      getAccessControlContext());
              }
              else {
                isEagerInit = (factory instanceof SmartFactoryBean &&
                      ((SmartFactoryBean<?>) factory).isEagerInit());
              }
              if (isEagerInit) {
                getBean(beanName);
              }
           }
        }
        else {
            // 创建bean
           getBean(beanName);
        }
     }
   }

   // Trigger post-initialization callback for all applicable beans...
   for (String beanName : beanNames) {
     Object singletonInstance = getSingleton(beanName);
     if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
           AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
              smartSingleton.afterSingletonsInstantiated();
              return null;
           }, getAccessControlContext());
        }
        else {
           smartSingleton.afterSingletonsInstantiated();
        }
     }
   }
}

preInstantiateSingletons 前半部分主要是遍历beanNames 创建Bean。创建完bean后判断各bean是不是SmartInitializingSingleton,如果是则执行 smartSingleton.afterSingletonsInstantiated()方法。

//org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated
public void afterSingletonsInstantiated() {
   List<EventListenerFactory> factories = getEventListenerFactories();
   ConfigurableApplicationContext context = getApplicationContext();
   String[] beanNames = context.getBeanNamesForType(Object.class);
   for (String beanName : beanNames) {
      if (!ScopedProxyUtils.isScopedTarget(beanName)) {
         Class<?> type = null;
         try {
            type = AutoProxyUtils.determineTargetClass(context.getBeanFactory(), beanName);
         }
         if (type != null) {
            if (ScopedObject.class.isAssignableFrom(type)) {
               try {
                  Class<?> targetClass = AutoProxyUtils.determineTargetClass(
                        context.getBeanFactory(), ScopedProxyUtils.getTargetBeanName(beanName));
                  if (targetClass != null) {
                     type = targetClass;
                  }
               }
            }
            try {
                //处理bean
               processBean(factories, beanName, type);
            }
         }
      }
   }
}
protected void processBean(
     final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
 
   //没有注解的class
   if (!this.nonAnnotatedClasses.contains(targetType)) {
     Map<Method, EventListener> annotatedMethods = null;
     try {
         //查找被注解EventListener的方法
        annotatedMethods = MethodIntrospector.selectMethods(targetType,
              (MethodIntrospector.MetadataLookup<EventListener>) method ->
                   AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
     }
     catch (Throwable ex) {
        // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
        if (logger.isDebugEnabled()) {
           logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
        }
     }
     if (CollectionUtils.isEmpty(annotatedMethods)) {
         //添加到没有注解的集合
        this.nonAnnotatedClasses.add(targetType);
        if (logger.isTraceEnabled()) {
           logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
        }
     }
     else {
        // Non-empty set of methods
        ConfigurableApplicationContext context = getApplicationContext();
        for (Method method : annotatedMethods.keySet()) {
           for (EventListenerFactory factory : factories) {
              if (factory.supportsMethod(method)) {
                Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
               //创建applicationListener,通过Adapter将注解形式的listener转换为普通的listener
                ApplicationListener<?> applicationListener =
                      factory.createApplicationListener(beanName, targetType, methodToUse);
                if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                   ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                }
               //添加listner到applicationContext
                context.addApplicationListener(applicationListener);
                break;
              }
           }
        }
        if (logger.isDebugEnabled()) {
           logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
                beanName + "': " + annotatedMethods);
        }
     }
   }
}
  • 查找类中标注@EventListener的方法
  • EventListenerFactory.createApplicationListener(beanName, targetType, methodToUse) 构造listener
  • 添加listener到Context中

    • 如果有applicationEventMulticaster,添加到ApplicationContext.applicationEventMulticaster中
    • 如果没有applicationEventMulticaster,添加到ApplicationContext.applicationListeners中。

相关文章:

  • 数据库设计,表与表的关系,一对一。One-To-One(1)
  • 对Emlog 6.0 Beta的完整代码审计过程
  • 学习微服务的路由网关zuul——路由转发和过滤器
  • 找一份好的前端工作,起点很重要
  • Docker镜像创建及建立私有仓库
  • RichTextBox简单扩展
  • 深入剖析Retrofit系列(一)来自官方的Retrofit开发手册(中英互译)
  • java编程——高并发大容量NoSQL解决方案探索
  • Android 模拟器下载、编译及调试
  • [译]常见网页设计错误一览
  • 面试官告诉你如何准备Java初级和高级的技术面试
  • Apache Pulsar 2.1 重磅发布
  • java监听器实现与原理
  • Jenkisn行RFS脚本问题汇总
  • 【模板】最小生成树
  • Fundebug计费标准解释:事件数是如何定义的?
  • JavaScript对象详解
  • Mithril.js 入门介绍
  • npx命令介绍
  • 创建一种深思熟虑的文化
  • 给github项目添加CI badge
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 前端代码风格自动化系列(二)之Commitlint
  • 如何正确理解,内页权重高于首页?
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​插件化DPI在商用WIFI中的价值
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (C)一些题4
  • (Python) SOAP Web Service (HTTP POST)
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (九十四)函数和二维数组
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)C#调用WebService 基础
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .Net Core缓存组件(MemoryCache)源码解析
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net 无限分类
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET序列化 serializable,反序列化
  • .NET中使用Protobuffer 实现序列化和反序列化
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [2016.7 test.5] T1
  • [bzoj1324]Exca王者之剑_最小割
  • [C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]
  • [CTO札记]如何测试用户接受度?
  • [GN] 设计模式——面向对象设计原则概述
  • [IE9] IE9 beta版下载链接