Spring笔记(8) - @EventListener注解探究

发布时间:2026/10/21 20:08:19
Spring笔记(8) - @EventListener注解探究 源码仓库Gitee·GitHub在上文中讲了Spring的事件监听机制流程是定义事件、监听器发布事件控制台输出监听到的事件内容。在上文的扩展中 使用 EventListener 注解来自定义监听器监听指定的事件比如下面的案例Component public class UserManagerListener { //ApplicationEvent能监听到所有的事件,如果为EmailEvent.class则只能监听到关于邮件的事件 //EventListener有两个参数可以不写直接在方法参数里面写上要监听的事件即可 // classes表示哪一个事件类 // condition当满足什么条件是会调用该方法 EventListener(classes ApplicationEvent.class) public void listen(ApplicationEvent event){ System.out.println(用户管理功能监听到的事件。。。。event); } }通过上面的案例发现代码比实现 ApplicationListener 接口更简洁那这个注解为什么功能这么强大呢接下来我们来分析它的源码/** * author Stephane Nicoll * author Sam Brannen * since 4.2 * see EventListenerMethodProcessor */ Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) Retention(RetentionPolicy.RUNTIME) Documented public interface EventListener { ....... }通过源码发现是通过使用 EventListenerMethodProcessor 处理器来解析该注解将标注了 EventListener 的方法进行解析, 获取拦截方法对拦截方法进行转换变成 ApplicationListener 然后放入到 IOC 容器中在publishEvent 时通过 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType)方法获取到 ApplicationListener 对象通过反射调用方法。下面是 EventListenerMethodProcessor 处理器的类图关系可以看到 EventListenerMethodProcessor 是实现了 BeanFactoryPostProcessor 和 SmartInitializingSingleton 这两个接口。在前文 Spring的BeanFactoryPostProcessor探究 中讲述了BeanFactoryPostProcessor 的执行时机在 refresh 容器的时候, 调用 invokeBeanFactoryPostProcessors() 方法时, 会执行 BeanFactoryPostProcessor#postProcessBeanFactory() 方法设置一个默认的监听器工厂 DefaultEventListenerFactory。/** * Registers {link EventListener} methods as individual {link ApplicationListener} instances. * Implements {link BeanFactoryPostProcessor} (as of 5.1) primarily for early retrieval, * avoiding AOP checks for this processor bean and its {link EventListenerFactory} delegates. * * author Stephane Nicoll * author Juergen Hoeller * since 4.2 * see EventListenerFactory * see DefaultEventListenerFactory */ public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor { ...... Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.beanFactory beanFactory; MapString, EventListenerFactory beans beanFactory.getBeansOfType(EventListenerFactory.class, false, false); ListEventListenerFactory factories new ArrayList(beans.values()); AnnotationAwareOrderComparator.sort(factories); //DefaultEventListenerFactory this.eventListenerFactories factories; } ....... }而SmartInitializingSingleton 这个接口只有一个方法 afterSingletonsInstantiated()这个方法在全部单实例创建完成之后执行接下来对这个方法进行深入探讨我们对 EventListenerMethodProcessor里面的实现方法 afterSingletonsInstantiated 打一个断点 debug 运行下从中我们可以看到流程是 IOC容器创建对象 -- refresh() -- finishBeanFactoryInitialization(beanFactory)(初始化剩下的所有单实例bean -- beanFactory.preInstantiateSingletons()(初始化剩下的所有单实例bean-- smartSingleton.afterSingletonsInstantiated()Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace(Pre-instantiating singletons in this); } // 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. //获取所有的注册bean名称 ListString beanNames new ArrayList(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... //先创建所有的单实例bean 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((PrivilegedActionBoolean) ((SmartFactoryBean?) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit (factory instanceof SmartFactoryBean ((SmartFactoryBean?) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName);//创建bean实例 } } } else { getBean(beanName);//创建bean实例 } } } // Trigger post-initialization callback for all applicable beans... //创建完成后进行遍历如果bean是SmartInitializingSingleton类型执行afterSingletonsInstantiated方法 for (String beanName : beanNames) { Object singletonInstance getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() ! null) { AccessController.doPrivileged((PrivilegedActionObject) () - { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }从上面可以看出其调用时机是遍历容器中注册的 BeanDefinition 调用所有 getBean() 方法创建实例之后, 才会开始遍历执行 afterSingletonsInstantiated() 方法。接下来详细解析下 EventListenerMethodProcessor 的 afterSingletonsInstantiated 方法重点看 processBean 方法Override public void afterSingletonsInstantiated() { ConfigurableListableBeanFactory beanFactory this.beanFactory; Assert.state(this.beanFactory ! null, No ConfigurableListableBeanFactory set); String[] beanNames beanFactory.getBeanNamesForType(Object.class); for (String beanName : beanNames) { if (!ScopedProxyUtils.isScopedTarget(beanName)) { Class? type null; try { type AutoProxyUtils.determineTargetClass(beanFactory, beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - lets ignore it. if (logger.isDebugEnabled()) { logger.debug(Could not resolve target class for bean with name beanName , ex); } } if (type ! null) { if (ScopedObject.class.isAssignableFrom(type)) { try { Class? targetClass AutoProxyUtils.determineTargetClass( beanFactory, ScopedProxyUtils.getTargetBeanName(beanName)); if (targetClass ! null) { type targetClass; } } catch (Throwable ex) { // An invalid scoped proxy arrangement - lets ignore it. if (logger.isDebugEnabled()) { logger.debug(Could not resolve target bean for scoped proxy beanName , ex); } } } try { processBean(beanName, type); } catch (Throwable ex) { throw new BeanInitializationException(Failed to process EventListener annotation on bean with name beanName , ex); } } } } } private void processBean(final String beanName, final Class? targetType) { //不包含没有注解的class注解是EventListener的类型是Spring容器的类型 if (!this.nonAnnotatedClasses.contains(targetType) AnnotationUtils.isCandidateClass(targetType, EventListener.class) !isSpringContainerClass(targetType)) { MapMethod, EventListener annotatedMethods null; try { //获取标注了 EventListener 注解的监听方法 annotatedMethods MethodIntrospector.selectMethods(targetType, (MethodIntrospector.MetadataLookupEventListener) method - AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); } catch (Throwable ex) { // An unresolvable type in a method signature, probably from a lazy bean - lets 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 this.applicationContext; Assert.state(context ! null, No ApplicationContext set); ListEventListenerFactory factories this.eventListenerFactories; Assert.state(factories ! null, EventListenerFactory List not initialized); for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { // 判断是否支持该方法 在DefaultEventListenerFactory中写死的返回true if (factory.supportsMethod(method)) { //选择方法 beanName 这里是AddDataEventListener的beanName 默认是addDataEventListener Method methodToUse AopUtils.selectInvocableMethod(method, context.getType(beanName)); //将监听方法转换为ApplicationListenerApplicationListenerMethodAdapter对象 ApplicationListener? applicationListener factory.createApplicationListener(beanName, targetType, methodToUse); // 如果是ApplicationListenerMethodAdapter对象 就把context和evaluator传进去 if (applicationListener instanceof ApplicationListenerMethodAdapter) { ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator); } //将创建的 ApplicationListener 加入到容器中 context.addApplicationListener(applicationListener); break; } } } if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() EventListener methods processed on bean beanName : annotatedMethods); } } } } //class是在org.springframework包下注解类型不是组件 private static boolean isSpringContainerClass(Class? clazz) { return (clazz.getName().startsWith(org.springframework.) !AnnotatedElementUtils.isAnnotated(ClassUtils.getUserClass(clazz), Component.class)); }后面就是添加listener到Context中1如果有applicationEventMulticaster添加到ApplicationContext.applicationEventMulticaster中2如果没有applicationEventMulticaster添加到ApplicationContext.applicationListeners中最后是触发事件监听了 AbstractApplicationContext.publishEvent -- SimpleApplicationEventMulticaster.multicastEvent -- invokeListener -- doInvokeListener -- ApplicationListenerMethodAdapter.onApplicationEventOverride public void onApplicationEvent(ApplicationEvent event) { processEvent(event); } ApplicationListenerMethodAdapter#processEvent public void processEvent(ApplicationEvent event) { Object[] args resolveArguments(event); if (shouldHandle(event, args)) { // 反射执行真正的方法 Object result doInvoke(args); if (result ! null) { handleResult(result); } else { logger.trace(No result object given - no result to handle); } } }在ApplicationListenerMethodAdapter.doInvoke中会反射执行真正的方法protected Object doInvoke(Object... args) { //获取目标对象 Object bean getTargetBean(); ReflectionUtils.makeAccessible(this.method); try { //反射执行监听方法 return this.method.invoke(bean, args); } catch (IllegalArgumentException ex) { assertTargetBean(this.method, bean, args); throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (IllegalAccessException ex) { throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (InvocationTargetException ex) { // Throw underlying exception Throwable targetException ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else { String msg getInvocationErrorMessage(bean, Failed to invoke event listener method, args); throw new UndeclaredThrowableException(targetException, msg); } } }

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询