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

[spring6: @EventListener @TransactionalEventListener ]-源码分析

推荐阅读:

  1. [spring6: ApplicationEvent & ApplicationListener & ApplicationEventMulticaster]-事件监听
  2. [spring6: BeanPostProcessor & BeanFactoryPostProcessor]-生命周期
  3. [spring6: AbstractApplicationContext.refresh()]-源码分析

EventListener

@EventListener 注解用于标记方法为事件监听器,允许指定事件类型、条件、执行策略和唯一标识符,用于处理应用中的事件。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface EventListener {@AliasFor("classes")Class<?>[] value() default {};@AliasFor("value")Class<?>[] classes() default {};String condition() default "";boolean defaultExecution() default true;String id() default "";}

TransactionalEventListener

@TransactionalEventListener 注解用于标记事件监听器方法,结合事务管理执行事件监听,允许指定事务阶段(如提交后)以及其他事件监听器的配置,如事件类型、条件、回退执行和唯一标识符等。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EventListener
public @interface TransactionalEventListener {TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;@AliasFor(annotation = EventListener.class, attribute = "classes")Class<?>[] value() default {};@AliasFor(annotation = EventListener.class, attribute = "classes")Class<?>[] classes() default {};@AliasFor(annotation = EventListener.class, attribute = "condition")String condition() default "";@AliasFor(annotation = EventListener.class, attribute = "defaultExecution")boolean fallbackExecution() default false;@AliasFor(annotation = EventListener.class, attribute = "id")String id() default "";}

EventListenerFactory

EventListenerFactory 接口定义了两个方法:supportsMethod 用于判断给定的方法是否支持创建事件监听器,而 createApplicationListener 用于根据方法、类和 bean 名称创建一个具体的 ApplicationListener 实例。

public interface EventListenerFactory {boolean supportsMethod(Method method);ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method);}

DefaultEventListenerFactory

DefaultEventListenerFactory 实现了 EventListenerFactoryOrdered 接口,用于创建常规的事件监听器。它的 supportsMethod 方法总是返回 true,表示所有方法都支持,因此可以用于任何带有事件监听注解的方法。通过 createApplicationListener 方法,返回一个 ApplicationListenerMethodAdapter 实例来适配事件监听方法。此外,getOrdersetOrder 方法允许设置监听器的执行顺序,默认顺序为 LOWEST_PRECEDENCE

public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {private int order = LOWEST_PRECEDENCE;public void setOrder(int order) {this.order = order;}@Overridepublic int getOrder() {return this.order;}@Overridepublic boolean supportsMethod(Method method) {return true;}@Overridepublic ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {return new ApplicationListenerMethodAdapter(beanName, type, method);}}

TransactionalEventListenerFactory

TransactionalEventListenerFactory 实现了 EventListenerFactoryOrdered 接口,用于创建带有 @TransactionalEventListener 注解的事件监听器。它通过 supportsMethod 方法判断给定的 Method 是否支持(即是否带有 @TransactionalEventListener 注解),并通过 createApplicationListener 方法返回一个 TransactionalApplicationListenerMethodAdapter 实例。此外,它还允许通过 setOrder 方法设置监听器的顺序,默认顺序为 50。

public class TransactionalEventListenerFactory implements EventListenerFactory, Ordered {private int order = 50;public void setOrder(int order) {this.order = order;}@Overridepublic int getOrder() {return this.order;}@Overridepublic boolean supportsMethod(Method method) {return AnnotatedElementUtils.hasAnnotation(method, TransactionalEventListener.class);}@Overridepublic ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {return new TransactionalApplicationListenerMethodAdapter(beanName, type, method);}}

RestrictedTransactionalEventListenerFactory

RestrictedTransactionalEventListenerFactoryTransactionalEventListenerFactory 的子类,用于创建 ApplicationListener 时,检查方法或类型上是否存在 @Transactional 注解。如果 @Transactional 注解的传播行为不是 REQUIRES_NEWNOT_SUPPORTED,则抛出 IllegalStateException 异常,确保只能在特定事务传播行为下使用 @TransactionalEventListener

public class RestrictedTransactionalEventListenerFactory extends TransactionalEventListenerFactory {@Overridepublic ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {Transactional txAnn = AnnotatedElementUtils.findMergedAnnotation(method, Transactional.class);if (txAnn == null) {txAnn = AnnotatedElementUtils.findMergedAnnotation(type, Transactional.class);}if (txAnn != null) {Propagation propagation = txAnn.propagation();if (propagation != Propagation.REQUIRES_NEW && propagation != Propagation.NOT_SUPPORTED) {throw new IllegalStateException("@TransactionalEventListener method must not be annotated with " +"@Transactional unless when declared as REQUIRES_NEW or NOT_SUPPORTED: " + method);}}return super.createApplicationListener(beanName, type, method);}}

EventListenerMethodProcessor

EventListenerMethodProcessor 是一个处理 @EventListener 注解的方法处理器,它负责在 Spring 容器启动时:

  1. afterSingletonsInstantiated() 方法中扫描所有 bean,查找带有 @EventListener 注解的方法,并为每个方法创建相应的 ApplicationListener
  2. 使用 EventListenerFactory 接口的实现类来创建这些监听器。
  3. processBean 方法中,利用 MethodIntrospector 查找所有带有 @EventListener 注解的方法,并调用工厂方法创建 ApplicationListener,然后注册到 ApplicationContext 中。

该类也支持延迟处理,忽略 lazy 初始化的 bean,并能够处理代理类和作用域代理。

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {protected final Log logger = LogFactory.getLog(getClass());@Nullableprivate ConfigurableApplicationContext applicationContext;@Nullableprivate ConfigurableListableBeanFactory beanFactory;@Nullableprivate List<EventListenerFactory> eventListenerFactories;private final StandardEvaluationContext originalEvaluationContext;@Nullableprivate final EventExpressionEvaluator evaluator;private final Set<Class<?>> nonAnnotatedClasses = ConcurrentHashMap.newKeySet(64);public EventListenerMethodProcessor() {this.originalEvaluationContext = new StandardEvaluationContext();this.evaluator = new EventExpressionEvaluator(this.originalEvaluationContext);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext,"ApplicationContext does not implement ConfigurableApplicationContext");this.applicationContext = (ConfigurableApplicationContext) applicationContext;}// 初始化并排序了所有 EventListenerFactory 实现类,为后续处理 @EventListener 注解的方法做好准备。@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {this.beanFactory = beanFactory;this.originalEvaluationContext.setBeanResolver(new BeanFactoryResolver(this.beanFactory));Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);List<EventListenerFactory> factories = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(factories);this.eventListenerFactories = factories;}// 在所有单例 bean 完成初始化后被调用,目的是遍历所有 bean 并解析它们是否包含 @EventListener 注解。// 如果 bean 是作用域代理,则会跳过处理。如果目标类无法解析,方法会忽略这些问题并继续处理其他 bean。	@Overridepublic void afterSingletonsInstantiated() {ConfigurableListableBeanFactory beanFactory = this.beanFactory;Assert.state(beanFactory != null, "No ConfigurableListableBeanFactory set");// 获取所有 bean 的名称String[] beanNames = beanFactory.getBeanNamesForType(Object.class);for (String beanName : beanNames) {// 排除作用域代理对象(即由 Spring 动态生成的代理对象),确保后续处理的是实际的 beanif (!ScopedProxyUtils.isScopedTarget(beanName)) {Class<?> type = null;try {// 获取bean classtype = AutoProxyUtils.determineTargetClass(beanFactory, beanName);}catch (Throwable ex) {// 无法解析的 bean 类型,可能是由于懒加载 bean 导致的——我们将忽略这个问题。// An unresolvable bean type, probably from a lazy bean - let's ignore it.if (logger.isDebugEnabled()) {logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);}}if (type != null) {// 判断一个 bean 是否为作用域对象,确保在处理的时候能正确理解它的作用域行为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 - let's 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.getMessage(), ex);}}}}}private void processBean(final String beanName, final Class<?> targetType) {if (!this.nonAnnotatedClasses.contains(targetType) &&AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&!isSpringContainerClass(targetType)) {Map<Method, EventListener> annotatedMethods = null;try {// 解析 targetType 中的所有方法,查找带有 @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)) {// 如果没有找到任何 @EventListener 注解的方法// 将该类 targetType 添加到 nonAnnotatedClasses 集合中,以便以后跳过这个类this.nonAnnotatedClasses.add(targetType);if (logger.isTraceEnabled()) {logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());}}else {// Non-empty set of methodsConfigurableApplicationContext context = this.applicationContext;Assert.state(context != null, "No ApplicationContext set");List<EventListenerFactory> factories = this.eventListenerFactories;Assert.state(factories != null, "EventListenerFactory List not initialized");for (Method method : annotatedMethods.keySet()) {for (EventListenerFactory factory : factories) {// 对每个方法,遍历所有可用的 EventListenerFactory,检查它是否支持该方法。if (factory.supportsMethod(method)) {Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse);if (applicationListener instanceof ApplicationListenerMethodAdapter alma) {alma.init(context, this.evaluator);}context.addApplicationListener(applicationListener);break;}}}if (logger.isDebugEnabled()) {logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +beanName + "': " + annotatedMethods);}}}}private static boolean isSpringContainerClass(Class<?> clazz) {return (clazz.getName().startsWith("org.springframework.") &&!AnnotatedElementUtils.isAnnotated(ClassUtils.getUserClass(clazz), Component.class));}}
http://www.xdnf.cn/news/15550.html

相关文章:

  • 100201组件拆分_编辑器-react-仿低代码平台项目
  • .NET 8.0 使用 WebSocket
  • Spring之【BeanDefinition】
  • cuda编程笔记(8)--线程束warp
  • 有n棍棍子,棍子i的长度为ai,想要从中选出3根棍子组成周长尽可能长的三角形。请输出最大的周长,若无法组成三角形则输出0。
  • Java List 集合详解:从基础到实战,掌握 Java 列表操作全貌
  • 自定义 django 中间件
  • 深度学习基础 | Softmax 函数原理详解 + Python实现 + 数学公式
  • 前缀和题目:表现良好的最长时间段
  • Leetcode 03 java
  • CKS认证 | Day6 监控、审计和运行时安全 sysdig、falco、审计日志
  • vue3 自定义vant-calendar header/footer/maincontent
  • EXCEL VBA合并当前工作簿的所有工作表sheet
  • Java全栈面试实录:从电商支付到AIGC的深度技术挑战
  • 机器学习:数据清洗与预处理 | Python
  • 控制台输出的JAVA格斗小游戏-面向对象
  • CMake综合学习1: Cmake的模块化设计
  • 我爱学算法之—— 前缀和(下)
  • 【yaml文件格式说明】
  • 18001.QGroundControl操作文档(一)
  • 【测试100问】为什么要做接口测试?
  • 让K线说话!用形态匹配功能透视通达信数据黑洞
  • 【带权的并集查找】 P9235 [蓝桥杯 2023 省 A] 网络稳定性|省选-
  • 小程序性能优化全攻略:提升用户体验的关键策略
  • 每天一个前端小知识 Day 33 - 虚拟列表与长列表性能优化实践(Virtual Scroll)
  • Oracle 关于一些连接故障的总结
  • NumPy 详解
  • 职业发展:把工作“玩”成一场“自我升级”的游戏
  • Web前端性能优化原理与方法
  • 【kubernetes】--安全认证机制