這裏是一個更完整的解決方案我做了一個類似的問題與希望的事務被提交後發送我的郵件(我可以使用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