EventListener原理

EventListener原理2019 独角兽企业重金招聘 Python 工程师标准 gt gt gt

目录

流程

容器的刷新流程如下:

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 
   
     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 
   
     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 
    
      ) ((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 
      ) () -> { 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 
   
     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 
   
     factories, final String beanName, final Class 
     targetType) { //没有注解的class if (!this.nonAnnotatedClasses.contains(targetType)) { Map 
    
      annotatedMethods = null; try { //查找被注解EventListener的方法 annotatedMethods = MethodIntrospector.selectMethods(targetType, (MethodIntrospector.MetadataLookup 
     
       ) 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中。

转载于:https://my.oschina.net/u//blog/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211496.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午10:17
下一篇 2026年3月18日 下午10:17


相关推荐

  • rebar3使用介绍(二)配置项

    rebar3使用介绍(二)配置项rebar3 使用介绍 二 全局配置 Alias 别名 ArtifactsCom 测试选项 CoverDialyze 目录 EDocEscriptE 最小 OTP 版本检查 OverridesHoo 钩子 shell 钩子功能钩子自写功能中可以 hook 的点 RELXSHELLXRe 本篇主要介绍 rebar3 的配置部分全局配置 rebar3 支持全局

    2026年3月19日
    3
  • Java数组(二维数组)「建议收藏」

    Java数组(二维数组)「建议收藏」目录前言多维数组二维数组声明二维数组创建二维数组访问二维数组遍历二维数组最后前言在上一篇文章Java数组(一维数组)中,我们学习了一维数组,那么今天我们来学习Java二维数组。多维数组数组元素除了可以是原始数据类型、对象类型之外,还可以是数组,即数组元素是数组,通过声明数组的数组来实现多维数组。多维数组的使用和二维数组使用相似,我们来介绍二维数组。二维数组声明二维数组声明二维数组语法有两种格式,例如:数组类型[][]数组名;

    2022年7月7日
    24
  • @Conditional注解详解

    @Conditional注解详解本文我们要陈述的是如何根据不同的条件来判定到底注入那个 Bean 即 Conditional 注解的用法

    2026年3月18日
    2
  • Delphi 2010下载+完美激活成功教程「建议收藏」

    Delphi 2010下载+完美激活成功教程「建议收藏」点击链接进入http://altd.embarcadero.com/download/RADStudio2010/delphicbuilder_2010_3615_win.isoRADStudio/

    2022年7月4日
    28
  • 五、eclipse如何创建一个ftl(FreeMarker)的文件和设置ftl文件的显示风格(ftl文件高亮显示)

    五、eclipse如何创建一个ftl(FreeMarker)的文件和设置ftl文件的显示风格(ftl文件高亮显示)1、首先需要在eclipse中去下载一个FreeMarker插件https://blog.csdn.net/IT_CREATE/article/details/86682538 2、创建ftl的文件(有多种方式,我会分别介绍)2.1利用file来创建,我们new个file文件写上页面的名字,后缀名改为ftl这样就创建好了,不过里面没有任何内容,我们需要自己添加一些基…

    2022年6月17日
    28
  • javascript返回上一步,后退的代码

    javascript返回上一步,后退的代码第一种方法:<ahref=”javascript:history.go(-1)”>返回上一步</a><ahref=”javascript:”οnclick=”history.back();”>返回上一页</a>第二种方法:<scriptlanguage=”javascript”>window.history.back(-1);</script>…

    2022年7月25日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号