为所有Spring托管事务注册beforeCommit回调

为所有Spring托管事务注册beforeCommit回调,spring,spring-transactions,Spring,Spring Transactions,我使用ChainedTransactionManager跨ActiveMQ和MySQL实现Best Effort 1PC,在我的示例中,数据库事务首先提交。为了减少失败窗口,我想在提交数据库事务之前检查ActiveMQConnection是否失败。一旦使用TransactionSynchronizationManager.registerSynchronization启动事务,我就可以执行此操作,但我想要的是注册为每个事务运行的代码块,而无需在代码中执行此操作 我可以将ChainedTransa

我使用ChainedTransactionManager跨ActiveMQ和MySQL实现Best Effort 1PC,在我的示例中,数据库事务首先提交。为了减少失败窗口,我想在提交数据库事务之前检查ActiveMQConnection是否失败。一旦使用TransactionSynchronizationManager.registerSynchronization启动事务,我就可以执行此操作,但我想要的是注册为每个事务运行的代码块,而无需在代码中执行此操作

我可以将ChainedTransactionManager子类化,但这似乎不是最干净的。有更好的方法吗


编辑:看来子类化ChainedTransactionManager不是一个好主意,因为它依赖于非公共的MultiTransactionStatus。创建一个新的平台TransactionManager,将其委托给ChainedTransactionManager是一种替代方法。

这就是我决定实施它的方式:

import org.apache.activemq.ActiveMQConnection;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.jms.connection.JmsResourceHolder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class JmsTransportFailureHandlingTransactionManager implements PlatformTransactionManager {

    private final ChainedTransactionManager chainedTransactionManager;

    public JmsTransportFailureHandlingTransactionManager(ChainedTransactionManager chainedTransactionManager) {
        this.chainedTransactionManager = chainedTransactionManager;
    }


    @Override
    public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        TransactionStatus transaction = chainedTransactionManager.getTransaction(definition);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void beforeCommit(boolean readOnly) {
                for (Object resource : TransactionSynchronizationManager.getResourceMap().values()) {
                    if (resource instanceof JmsResourceHolder) {
                        ActiveMQConnection connection = (ActiveMQConnection) ((JmsResourceHolder) resource).getConnection();
                        if (connection.isTransportFailed()) {
                            throw new IllegalStateException("ActiveMQ transport failed.");
                        }
                    }
                }
            }
        });

        return transaction;
    }

    @Override
    public void commit(TransactionStatus status) throws TransactionException {
        chainedTransactionManager.commit(status);
    }

    @Override
    public void rollback(TransactionStatus status) throws TransactionException {
        chainedTransactionManager.rollback(status);
    }
}