这里是一个更完整的解决方案我做了一个类似的问题与希望的事务被提交后发送我的邮件(我可以使用RabbitMQ的TX但他们宁可慢)。
public class MessageBusUtils {
public static Optional<MessageBusResourceHolder> getTransactionalResourceHolder(TxMessageBus messageBus) {
if (! TransactionSynchronizationManager.isActualTransactionActive()) {
return Optional.absent();
}
MessageBusResourceHolder o = (MessageBusResourceHolder) TransactionSynchronizationManager.getResource(messageBus);
if (o != null) return Optional.of(o);
o = new MessageBusResourceHolder();
TransactionSynchronizationManager.bindResource(messageBus, o);
o.setSynchronizedWithTransaction(true);
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new MessageBusResourceSynchronization(o, messageBus));
}
return Optional.of(o);
}
private static class MessageBusResourceSynchronization extends ResourceHolderSynchronization<MessageBusResourceHolder, TxMessageBus> {
private final TxMessageBus messageBus;
private final MessageBusResourceHolder holder;
public MessageBusResourceSynchronization(MessageBusResourceHolder resourceHolder, TxMessageBus resourceKey) {
super(resourceHolder, resourceKey);
this.messageBus = resourceKey;
this.holder = resourceHolder;
}
@Override
protected void cleanupResource(MessageBusResourceHolder resourceHolder, TxMessageBus resourceKey,
boolean committed) {
resourceHolder.getPendingMessages().clear();
}
@Override
public void afterCompletion(int status) {
if (status == TransactionSynchronization.STATUS_COMMITTED) {
for (Object o : holder.getPendingMessages()) {
messageBus.post(o, false);
}
}
else {
holder.getPendingMessages().clear();
}
super.afterCompletion(status);
}
}
}
public class MessageBusResourceHolder extends ResourceHolderSupport {
private List<Object> pendingMessages = Lists.newArrayList();
public void addMessage(Object message) {
pendingMessages.add(message);
}
protected List<Object> getPendingMessages() {
return pendingMessages;
}
}
现在,在你的类,你实际发送你会做
@Override
public void postAfterCommit(Object o) {
Optional<MessageBusResourceHolder> holder = MessageBusTxUtils.getTransactionalResourceHolder(this);
if (holder.isPresent()) {
holder.get().addMessage(o);
}
else {
post(o, false);
}
}
对不起,长篇大论的编码样本,但希望这将显示一个人怎么办后提交的东西消息。
但是,一个好的建议不会在任何交易中执行?我只想要完成任务。另外,我可以使用默认弹簧(我不使用代码编织)的AOP注释只是JDK代理。 – Justin 2011-03-18 21:14:33
当方法抛出异常时,返回通知不会运行,所以这依赖于@Transactional在方法返回结果时提交并在抛出异常时回滚,这通常会发生。这些方面是通过Spring动态代理来调用的,因此它不会执行任何代码编织(除非您不提供用于Spring的代理接口,其中spring将退回到在运行时使用cglib编译代码)。 – krock 2011-03-18 21:20:14
+1有趣,但我仍然不确信没有测试。至少有2个@AfterReturning参与:@Transactional,然后我的自定义方面。如果@Transactional运行,那么我的运行一切都很好;但是,我将在之前执行的另一个命令中 - 与事务提交状态无关。 – Justin 2011-03-18 23:52:24