@TransactionalEventListener的使用
@Component
public class EsSaveTransactionalEventListener {
@Resource
private EsDocumentDao esDocumentDao;
@Resource
private PushMessageSender pushMessageSender;
// 事务提交前触发的方法
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void commitBefore(MyTransactionEvent myTransactionEvent) {
// 从Es的ThreadLocal里边取出之前放进去的数据
List<DocWriteRequest<?>> docWriteRequests = EsBatchSaveUtils.getAndRemove();
if (CollectionUtils.isNotEmpty(docWriteRequests)) {
log.info("获取待存储数据,数量 :{}", docWriteRequests.size());
// 事务提交前,批量存储数据,保证es和mysql数据的一致性
documentDao.bulk(Lists.newArrayList(docWriteRequests));
}
}
// 事务提交后
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommit(TransactionEvent transactionEvent) {
// 从消息的ThreadLocal中取出数据
Map<PushMessageUniqueKey, BaseMessage> pushMessageParams = MessageNotifyUtils.getAndRemove();
if (MapUtils.isNotEmpty(pushMessageParams)) {
log.info("获取待通知消息,数量 :{}", pushMessageParams.size());
// 事务提交之后,发送mq,进行数据的异步处理,保证数据的一致性
pushMessageParams.forEach((key, message)-> pushMessageSender.send(key.getTopicType(), message));
}
}
// 事务完成处理
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void afterCompletion(TransactionEvent transactionEvent) {
// 从redis的threadlocal里取出锁
List<RedissionLock> redissonLocks = LockReleaseUtils.getAndRemoveRedissonLock();
if (CollectionUtils.isNotEmpty(redissonLocks)) {
log.info("获取待释放RedissonLock锁数,数量 :{}", redissonLocks.size());
try {
// 释放需要释放的锁
redisLockService.unLock(redissonLocks);
} catch (Exception e) {
log.error("释放RedissonLock锁失败", e);
}
}
}
}
从上面的这个类可以看出,通过事务注解可以保证数据的一致性,也能保证在事务完成之后,锁能够释放.
1、监听器初始化
因为@TransactionalEventListener注解和事务相关,所以从Spring boot开启事务注解的地方开始分析,@EnableTransactionManagement:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//是否直接代理目标类
boolean proxyTargetClass() default false;
//通知模式,默认是代理
AdviceMode mode() default AdviceMode.PROXY;
//顺序
int order() default Ordered.LOWEST_PRECEDENCE;
}
@EnableTransactionManagement导入了选择器TransactionManagementConfigurationSelector:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
// 默认
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
这里主要对ProxyTransactionManagementConfiguration进行分析
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
ProxyTransactionManagementConfiguration定义的这几个基础设施类,来实现事务逻辑织入的.
从上面的继承关系可以看到ProxyTransactionManagementConfiguration继承自AbstractTransactionManagementConfiguration类.
AbstractTransactionManagementConfiguration类定义了一个bean:
@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory();
}
这个bean所在的类定义了创建事件监听器的方法:
@Override
public boolean supportsMethod(Method method) {
// 指定目标方法是否是支持的监听器的类型,
// 这里的判断逻辑就是如果目标方法上包含有TransactionalEventListener
// 则说明是一个事务监听器
return AnnotatedElementUtils.hasAnnotation(method, TransactionalEventListener.class);
}
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
// 根据用户使用@TransactionalEventListener注解的方法创建事件监听器代理
// 在应用启动的时候EventListenerMethodProcessor中调用
return new ApplicationListenerMethodTransactionalAdapter(beanName, type, method);
}
下面看一下ApplicationListenerMethodTransactionalAdapter的创建实现:
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 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);
}
}
}
}
2.事务事件调用与监听器触发
@Autowired
protected ApplicationEventPublisher applicationEventPublisher;
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
调用ApplicationEventPublisher#publishEvent会调用AbstractApplicationContext#publishEvent:
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 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);
}
}
}
这里是一个递归调用,当前上下文先发布事件,然后递归找父上下文发布事件,最终会调用SimpleApplicationEventMulticaster#multicastEvent来发布事件:
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
这里是从上下文中先获取监听器集合,然后如果有任务执行器就调用任务执行器执行监听器逻辑(多线程),否则当前线程调用监听器逻辑,然后看invokeListener实现:
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 调用监听器的onApplicationEvent方法
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
到这里就比较清晰了,我们自定义事件监听器都实现了ApplicationListener接口,此处会调用监听器的onApplicationEvent方法执行自定义逻辑。
回顾下:
ApplicationListenerMethodTransactionalAdapter#onApplicationEvent
如果检测到当前上下文有活跃的事务,那么就把监听器逻辑注册到事务中,等到事务执行到指定的节点触发监听器逻辑,否则如果检测到TransactionalEventListener.fallbackExecution属性为true(如果没有事务,是否处理事件),则直接调用处理事件逻辑,否则返回调用。
我们直接看当前逻辑在事务中的逻辑:
// 创建TransactionSynchronization
private TransactionSynchronization createTransactionSynchronization(ApplicationEvent event) {
return new TransactionSynchronizationEventAdapter(this, event, this.annotation.phase());
}
// 把事务监听器注册到事务生命周期中
public static void registerSynchronization(TransactionSynchronization synchronization)
throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null");
Set<TransactionSynchronization> synchs = synchronizations.get();
if (synchs == null) {
throw new IllegalStateException("Transaction synchronization is not active");
}
synchs.add(synchronization);
}
上面把监听器注册到了事务的生命周期中,那什么时候触发呢?
刚开始提到TransactionSynchronization的TransactionInterceptor这个类,这个类会对加事务注解的逻辑执行的时候进行拦截,然后执行invoke方法:
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
在invokeWithinTransaction逻辑中会调用commitTransactionAfterReturning方法:
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
然后会调用事务管理器执行事务状态的提交逻辑:
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
} else {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
this.logger.debug("Transactional code has requested rollback");
}
this.processRollback(defStatus, false);
} else if (!this.shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
this.logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
this.processRollback(defStatus, true);
} else {
this.processCommit(defStatus);
}
}
}
如果事务已结束,异常终止,如果事务需要回滚则执行processRollback,否则执行processCommit提交,
看一下回滚的代码:
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
//1.处理事务提交前事件监听逻辑
this.triggerBeforeCompletion(status);
//回滚逻辑
if (status.hasSavepoint()) {
if (status.isDebug()) {
this.logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
} else if (status.isNewTransaction()) {
if (status.isDebug()) {
this.logger.debug("Initiating transaction rollback");
}
this.doRollback(status);
} else {
if (status.hasTransaction()) {
if (!status.isLocalRollbackOnly() && !this.isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
this.logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
} else {
if (status.isDebug()) {
this.logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
this.doSetRollbackOnly(status);
}
} else {
this.logger.debug("Should roll back transaction but cannot - no transaction available");
}
if (!this.isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
} catch (Error | RuntimeException var8) {
this.triggerAfterCompletion(status, 2);
throw var8;
}
//2触发事务提交后监听逻辑
this.triggerAfterCompletion(status, 1);
if (unexpectedRollback) {
throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
}
} finally {
this.cleanupAfterCompletion(status);
}
}
看一下triggerAfterCompletion实现:
protected final void triggerBeforeCompletion(DefaultTransactionStatus status) {
// 如果当前阶段没有事务或者新事务则执行后置回调逻辑invokeAfterCompletion:
if (status.isNewSynchronization()) {
if (status.isDebug()) {
this.logger.trace("Triggering beforeCompletion synchronization");
}
TransactionSynchronizationUtils.triggerAfterCommit();
}
}
看一下triggerAfterCompletion实现:
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
if (status.isNewSynchronization()) {
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
TransactionSynchronizationManager.clearSynchronization();
if (status.hasTransaction() && !status.isNewTransaction()) {
if (!synchronizations.isEmpty()) {
this.registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
}
} else {
if (status.isDebug()) {
this.logger.trace("Triggering afterCompletion synchronization");
}
// 如果当前阶段没有事务或者新事务则执行后置回调逻辑invokeAfterCompletion:
this.invokeAfterCompletion(synchronizations, completionStatus);
}
}
}
然后调用TransactionSynchronizationUtils#invokeAfterCompletion方法:
protected final void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) {
TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus);
}
public static void invokeAfterCompletion(@Nullable List<TransactionSynchronization> synchronizations,
int completionStatus) {
if (synchronizations != null) {
for (TransactionSynchronization synchronization : synchronizations) {
try {
synchronization.afterCompletion(completionStatus);
}
catch (Throwable tsex) {
logger.error("TransactionSynchronization.afterCompletion threw exception", tsex);
}
}
}
}
获取到注册到当前事务的事件列表并执行,前边我们注册的是TransactionSynchronizationEventAdapter,直接看其afterCompletion实现:
public void afterCompletion(int status) {
if (this.phase == TransactionPhase.AFTER_COMMIT && status == 0) {
this.processEvent();
} else if (this.phase == TransactionPhase.AFTER_ROLLBACK && status == 1) {
this.processEvent();
} else if (this.phase == TransactionPhase.AFTER_COMPLETION) {
this.processEvent();
}
}
从@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)可以看出我们注册事件监听的截断是TransactionPhase.AFTER_ROLLBACK,逻辑会进入第二个分支调用processEvent方法:
protected void processEvent() {
this.listener.processEvent(this.event);
}
到这里就执行到我们自定义监听器的逻辑了.
public void processEvent(ApplicationEvent event) {
// 处理事务事件的相关参数,这里主要是判断TransactionalEventListener注解中是否配置了value或classes属性
// 如果配置了,则将方法参数转换为该指定类型传给监听的方法;
// 如果没有配置,则判断目标方法是ApplicationEvent类型还是PayloadApplicationEvent类型,是则转换为该类型传入
Object[] args = resolveArguments(event);
// 这里主要是获取TransactionalEventListener注解中的condition属性,
// 然后通过 Spring expression language将其与目标类和方法进行匹配
if (shouldHandle(event, args)) {
// 通过处理得到的参数借助于反射调用事务监听方法
Object result = doInvoke(args);
if (result != null) {
// 对方法的返回值进行处理
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
处理事务监听方法的参数
protected Object[] resolveArguments(ApplicationEvent event) {
// 获取发布事务事件时传入的参数类型
ResolvableType declaredEventType = getResolvableType(event);
if (declaredEventType == null) {
return null;
}
// 如果事务监听方法的参数个数为0,则直接返回
if (this.method.getParameterCount() == 0) {
return new Object[0];
}
// 如果事务监听方法的参数不为ApplicationEvent或PayloadApplicationEvent,则直接将发布事务
// 事件时传入的参数当做事务监听方法的参数传入。从这里可以看出,如果事务监听方法的参数不是
// ApplicationEvent或PayloadApplicationEvent类型,那么其参数必须只能有一个,并且这个
// 参数必须与发布事务事件时传入的参数一致
Class<?> eventClass = declaredEventType.getRawClass();
if ((eventClass == null || !ApplicationEvent.class.isAssignableFrom(eventClass)) &&
event instanceof PayloadApplicationEvent) {
return new Object[] {((PayloadApplicationEvent) event).getPayload()};
} else {
// 如果参数类型为ApplicationEvent或PayloadApplicationEvent,则直接将其传入事务事件方法
return new Object[] {event};
}
}
判断事务事件方法方法是否需要进行事务事件处理
private boolean shouldHandle(ApplicationEvent event, @Nullable Object[] args) {
if (args == null) {
return false;
}
String condition = getCondition();
if (StringUtils.hasText(condition)) {
Assert.notNull(this.evaluator, "EventExpressionEvaluator must no be null");
EvaluationContext evaluationContext = this.evaluator.createEvaluationContext(
event, this.targetClass, this.method, args, this.applicationContext);
return this.evaluator.condition(condition, this.methodKey, evaluationContext);
}
return true;
}
对事务事件方法的返回值进行处理,这里的处理方式主要是将其作为一个事件继续发布出去,这样就可以在
一个统一的位置对事务事件的返回值进行处理
protected void handleResult(Object result) {
// 如果返回值是数组类型,则对数组元素一个一个进行发布
if (result.getClass().isArray()) {
Object[] events = ObjectUtils.toObjectArray(result);
for (Object event : events) {
publishEvent(event);
}
} else if (result instanceof Collection<?>) {
// 如果返回值是集合类型,则对集合进行遍历,并且发布集合中的每个元素
Collection<?> events = (Collection<?>) result;
for (Object event : events) {
publishEvent(event);
}
} else {
// 如果返回值是一个对象,则直接将其进行发布
publishEvent(result);
}
}