• 聊聊spring的TransactionalEventListener


    本文主要研究一下spring的TransactionalEventListener

    TransactionalEventListener

    org/springframework/transaction/event/TransactionalEventListener.java

    /**
     * An {@link EventListener} that is invoked according to a {@link TransactionPhase}.
     *
     * 

    If the event is not published within an active transaction, the event is discarded * unless the {@link #fallbackExecution} flag is explicitly set. If a transaction is * running, the event is processed according to its {@code TransactionPhase}. * *

    Adding {@link org.springframework.core.annotation.Order @Order} to your annotated * method allows you to prioritize that listener amongst other listeners running before * or after transaction completion. * * @author Stephane Nicoll * @author Sam Brannen * @since 4.2 */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @EventListener public @interface TransactionalEventListener { /** * Phase to bind the handling of an event to. *

    The default phase is {@link TransactionPhase#AFTER_COMMIT}. *

    If no transaction is in progress, the event is not processed at * all unless {@link #fallbackExecution} has been enabled explicitly. */ TransactionPhase phase() default TransactionPhase.AFTER_COMMIT; /** * Whether the event should be processed if no transaction is running. */ boolean fallbackExecution() default false; /** * Alias for {@link #classes}. */ @AliasFor(annotation = EventListener.class, attribute = "classes") Class[] value() default {}; /** * The event classes that this listener handles. *

    If this attribute is specified with a single value, the annotated * method may optionally accept a single parameter. However, if this * attribute is specified with multiple values, the annotated method * must not declare any parameters. */ @AliasFor(annotation = EventListener.class, attribute = "classes") Class[] classes() default {}; /** * Spring Expression Language (SpEL) attribute used for making the event * handling conditional. *

    The default is {@code ""}, meaning the event is always handled. * @see EventListener#condition */ String condition() default ""; }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    TransactionalEventListener是EventListener的事务感知版本,默认的是TransactionPhase是AFTER_COMMIT

    ApplicationListenerMethodTransactionalAdapter

    org/springframework/transaction/event/ApplicationListenerMethodTransactionalAdapter.java

    /**
     * {@link GenericApplicationListener} adapter that delegates the processing of
     * an event to a {@link TransactionalEventListener} annotated method. Supports
     * the exact same features as any regular {@link EventListener} annotated method
     * but is aware of the transactional context of the event publisher.
     *
     * 

    Processing of {@link TransactionalEventListener} is enabled automatically * when Spring's transaction management is enabled. For other cases, registering * a bean of type {@link TransactionalEventListenerFactory} is required. * * @author Stephane Nicoll * @author Juergen Hoeller * @since 4.2 * @see ApplicationListenerMethodAdapter * @see TransactionalEventListener */ class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerMethodAdapter { private final TransactionalEventListener annotation; public ApplicationListenerMethodTransactionalAdapter(String beanName, Class targetClass, Method method) { super(beanName, targetClass, method); TransactionalEventListener ann = AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class); if (ann == null) { throw new IllegalStateException("No TransactionalEventListener annotation found on method: " + method); } this.annotation = ann; } @Override public void onApplicationEvent(ApplicationEvent event) { if (TransactionSynchronizationManager.isSynchronizationActive() && TransactionSynchronizationManager.isActualTransactionActive()) { TransactionSynchronization transactionSynchronization = createTransactionSynchronization(event); TransactionSynchronizationManager.registerSynchronization(transactionSynchronization); } else if (this.annotation.fallbackExecution()) { if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) { logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase"); } processEvent(event); } else { // No transactional event execution at all if (logger.isDebugEnabled()) { logger.debug("No transaction is active - skipping " + event); } } } private TransactionSynchronization createTransactionSynchronization(ApplicationEvent event) { return new TransactionSynchronizationEventAdapter(this, event, this.annotation.phase()); } private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter { private final ApplicationListenerMethodAdapter listener; private final ApplicationEvent event; private final TransactionPhase phase; public TransactionSynchronizationEventAdapter(ApplicationListenerMethodAdapter listener, ApplicationEvent event, TransactionPhase phase) { this.listener = listener; this.event = event; this.phase = phase; } @Override public int getOrder() { return this.listener.getOrder(); } @Override public void beforeCommit(boolean readOnly) { if (this.phase == TransactionPhase.BEFORE_COMMIT) { processEvent(); } } @Override public void afterCompletion(int status) { if (this.phase == TransactionPhase.AFTER_COMMIT && status == STATUS_COMMITTED) { processEvent(); } else if (this.phase == TransactionPhase.AFTER_ROLLBACK && status == STATUS_ROLLED_BACK) { processEvent(); } else if (this.phase == TransactionPhase.AFTER_COMPLETION) { processEvent(); } } protected void processEvent() { this.listener.processEvent(this.event); } } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    ApplicationListenerMethodTransactionalAdapter继承了ApplicationListenerMethodAdapter,它的构造器会找到指定方法的TransactionalEventListener信息;其onApplicationEvent方法在有事务的时候会创建并注册transactionSynchronization到当前事务,没有事务若允许fallbackExecution也会执行processEvent
    TransactionSynchronizationEventAdapter只是覆盖了beforeCommit及afterCompletion两个方法,在afterCompletion方法中根据status的值与phase的值的匹配关系决定是否执行processEvent

    TransactionalEventListenerFactory

    org/springframework/transaction/event/TransactionalEventListenerFactory.java

    /**
     * {@link EventListenerFactory} implementation that handles {@link TransactionalEventListener}
     * annotated methods.
     *
     * @author Stephane Nicoll
     * @since 4.2
     */
    public class TransactionalEventListenerFactory implements EventListenerFactory, Ordered {
    
    	private int order = 50;
    
    
    	public void setOrder(int order) {
    		this.order = order;
    	}
    
    	@Override
    	public int getOrder() {
    		return this.order;
    	}
    
    
    	@Override
    	public boolean supportsMethod(Method method) {
    		return AnnotatedElementUtils.hasAnnotation(method, TransactionalEventListener.class);
    	}
    
    	@Override
    	public ApplicationListener createApplicationListener(String beanName, Class type, Method method) {
    		return new ApplicationListenerMethodTransactionalAdapter(beanName, type, method);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    TransactionalEventListenerFactory用于创建ApplicationListenerMethodTransactionalAdapter

    EventListenerMethodProcessor

    org/springframework/context/event/EventListenerMethodProcessor.java

    public class EventListenerMethodProcessor
    		implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
    
    	//......
    
    	@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 - let's 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 - 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);
    					}
    				}
    			}
    		}
    	}
    
    	private void processBean(final String beanName, final Class targetType) {
    		if (!this.nonAnnotatedClasses.contains(targetType) &&
    				AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
    				!isSpringContainerClass(targetType)) {
    
    			Map annotatedMethods = null;
    			try {
    				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 = this.applicationContext;
    				Assert.state(context != null, "No ApplicationContext set");
    				List factories = this.eventListenerFactories;
    				Assert.state(factories != null, "EventListenerFactory List not initialized");
    				for (Method method : annotatedMethods.keySet()) {
    					for (EventListenerFactory factory : factories) {
    						if (factory.supportsMethod(method)) {
    							Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
    							ApplicationListener applicationListener =
    									factory.createApplicationListener(beanName, targetType, methodToUse);
    							if (applicationListener instanceof ApplicationListenerMethodAdapter) {
    								((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
    							}
    							context.addApplicationListener(applicationListener);
    							break;
    						}
    					}
    				}
    				if (logger.isDebugEnabled()) {
    					logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
    							beanName + "': " + annotatedMethods);
    				}
    			}
    		}
    	}
    
    	//......
    }		
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    EventListenerMethodProcessor实现了SmartInitializingSingleton接口,其afterSingletonsInstantiated方法先确定type,然后执行processBean,该方法会先收集annotatedMethods,然后遍历该方法,在遍历factories针对支持该方法的factory执行createApplicationListener,添加到context中

    小结

    TransactionalEventListener是EventListener的事务感知版本,默认的是TransactionPhase是AFTER_COMMIT,TransactionSynchronizationEventAdapter只是覆盖了beforeCommit及afterCompletion两个方法,在afterCompletion方法中根据status的值与phase的值的匹配关系决定是否执行processEvent,因而这里抛出的异常会被捕获并log下来

    doc

  • 相关阅读:
    Tableau 计算排名或行号
    docker系列(5) - docker仓库
    mac的node版本安装及升降级
    k8s-----7、Pod健康检查
    基于java图书馆借阅管理系统获取(java毕业设计)
    Linux C++ OpenVINO 物体检测 Demo
    渗透测试-渗透中403/401页面绕过的思路总结
    Android 状态栏显示运营商名称
    Java反射
    win10 上PHP artisan storage:link 出现 symlink (): Protocol error的解决办法
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/132799869