TransactionManager Spring Boot的动态选择

时间:2018-06-28 16:29:04

标签: java spring-boot spring-transactions

我正在将现有的Spring应用程序转换为Spring Boot应用程序。在我现有的应用程序中,我们需要连接到多个数据库,并且已经通过定义多个数据源并根据条件获取相应的bean来实现了这一点。还使用自定义实现TransactionInterceptor选择了交易管理器。

@Override
public TransactionAttributeSource getTransactionAttributeSource() {
    final TransactionAttributeSource origTxAttrSource = super.getTransactionAttributeSource();
    return new TransactionAttributeSource() {

        @Override
        public TransactionAttribute getTransactionAttribute(final Method method, final Class<?> targetClass) {
            TransactionAttribute txAttr = origTxAttrSource.getTransactionAttribute(method, targetClass);
            String database = (String) ThreadContext.get("database");
            if (database != null && StringUtils.isNotBlank(database)) {
                if (txAttr instanceof DefaultTransactionAttribute) {
                    ((DefaultTransactionAttribute) txAttr).setQualifier("txManager" + database);
                }
            }
            return txAttr;
        }
    };
}

通过BeanFactoryPostProcessor,我们包括了该拦截器

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
         String[] names = beanFactory.getBeanNamesForType(TransactionInterceptor.class);
        for (String name : names) {
            BeanDefinition bd = beanFactory.getBeanDefinition(name);
            bd.setBeanClassName(MyTransactionInterceptor.class.getName());

        }
}

这在Spring 4.X中工作得很好。

现在,我们正朝着Spring Boot前进,我正在尝试转换相同的方法。我可以看到正在调用bean工厂,但是没有发现Custom Interceptor类正在发生调用。这导致我的@Transactional失败,因为有多个合格的bean。

我是否缺少有关Spring Boot配置的信息?

(这种动态交易管理的方法是通过参考博客http://blog.tirasa.net/dynamic-springs--at-transactional.html

1 个答案:

答案 0 :(得分:2)

最终的答案是将工厂类和工厂bean名称设置为null,这导致事务拦截器被调用。我还没有弄清楚这将如何影响这些拦截器的调用(与这些字段中的值一样)(它们指向ProxyTransaction类,因为它是由transactionInterceptor bean创建的)。

最终代码的格式为-

TransactionInterceptor类

@Component
public class TransactionInterceptorReplacer implements BeanFactoryPostProcessor {

@Override
    public void postProcessBeanFactory(final ConfigurableListableBeanFactory factory) throws BeansException {
        String[] names = factory.getBeanNamesForType(TransactionInterceptor.class);
        for (String name : names) {
            BeanDefinition bd = factory.getBeanDefinition(name);
            bd.setBeanClassName(MyTransactionInterceptor.class.getName());
            bd.setFactoryBeanName(null);
            bd.setFactoryMethodName(null);
       }
   }
}