[spring6: @EventListener @TransactionalEventListener ]-源码分析
推荐阅读:
- [spring6: ApplicationEvent & ApplicationListener & ApplicationEventMulticaster]-事件监听
- [spring6: BeanPostProcessor & BeanFactoryPostProcessor]-生命周期
- [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
实现了 EventListenerFactory
和 Ordered
接口,用于创建常规的事件监听器。它的 supportsMethod
方法总是返回 true
,表示所有方法都支持,因此可以用于任何带有事件监听注解的方法。通过 createApplicationListener
方法,返回一个 ApplicationListenerMethodAdapter
实例来适配事件监听方法。此外,getOrder
和 setOrder
方法允许设置监听器的执行顺序,默认顺序为 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
实现了 EventListenerFactory
和 Ordered
接口,用于创建带有 @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
RestrictedTransactionalEventListenerFactory
是 TransactionalEventListenerFactory
的子类,用于创建 ApplicationListener
时,检查方法或类型上是否存在 @Transactional
注解。如果 @Transactional
注解的传播行为不是 REQUIRES_NEW
或 NOT_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 容器启动时:
- 在
afterSingletonsInstantiated()
方法中扫描所有 bean,查找带有@EventListener
注解的方法,并为每个方法创建相应的ApplicationListener
。 - 使用
EventListenerFactory
接口的实现类来创建这些监听器。 - 在
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));}}