开启事务

注册Rabbit事务管理器,本质还是实现了Spring的PlatformTransactionManager

1
2
3
4
5
6
@Bean
public RabbitTransactionManager rabbitTransactionManager(CachingConnectionFactory connectionFactory, RabbitTemplate rabbitTemplate) {
// channel开启事务支持
rabbitTemplate.setChannelTransacted(true);
return new RabbitTransactionManager(connectionFactory);
}

发送消息

1
2
3
4
5
6
7
8
9
10
11
12
//使用spring事务,必须使用该注解
@Transactional
public void send(String messageStr, String routeKey) {
String messageId = String.valueOf(UUID.randomUUID());
Body body = new Body();
body.setCreateTime(DateTime.now());
body.setMessage(messageStr);
body.setMessageId(messageId);
//将消息携带绑定键值,发送到交换机
rabbitTemplate.convertAndSend("testTopic", routeKey, body);
System.out.println(rabbitTemplate.isChannelTransacted());
}

拦截器

我们知道spring声明式事务的核心就是aop拦截器,那么spring是如何拦截rabbit的呢

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
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = this.getTransactionAttributeSource();
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
Object result;
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
//该部分代码比较复杂,没有贴出,可以自行查看,其实就是我没看懂,所以没贴
} else {
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

try {
//这里代表我们实际的方法,即加上@Transactional注解的方法,spring在注册bean时,会扫描包含@Transactional注解的方法,然后生成代理方法,即aop拦截
result = invocation.proceedWithInvocation();
} catch (Throwable var17) {
//如果发生了报错,则回滚,调用PlatformTransactionManager的rollback(),最终调用channel的txRollback()
this.completeTransactionAfterThrowing(txInfo, var17);
throw var17;
} finally {
this.cleanupTransactionInfo(txInfo);
}
//如果执行成功,则提交,调用PlatformTransactionManager的commit(),最终调用channel的txCommit()
this.commitTransactionAfterReturning(txInfo);
return result;
}
}
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
protected void completeTransactionAfterThrowing(@Nullable TransactionAspectSupport.TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
}
//这里主要是判断事务传播机制,以及错误类型是否需要回滚,错误类型由@Transactional注解的rollbackFor属性决定,默认RuntimeException
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch (TransactionSystemException var6) {
this.logger.error("Application exception overridden by rollback exception", ex);
var6.initApplicationException(ex);
throw var6;
} catch (Error | RuntimeException var7) {
this.logger.error("Application exception overridden by rollback exception", ex);
throw var7;
}
} else {
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
} catch (TransactionSystemException var4) {
this.logger.error("Application exception overridden by commit exception", ex);
var4.initApplicationException(ex);
throw var4;
} catch (Error | RuntimeException var5) {
this.logger.error("Application exception overridden by commit exception", ex);
throw var5;
}
}
}

}

总结

rabbitmq本身的事务是通过channel.txSelect、channel.txCommit、channel.txRollback实现的,spring是在rabbitmq本身事务的基础上加了一层事务


本站总访问量:次本站总访问数:人
本站由 Peng Tong 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。