java - Spring Boot TransactionManager动态选择

标签 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 工厂正在被调用,但我没有发现自定义拦截器类发生调用。这会导致我的 @Transactional 失败,因为有多个符合条件的 bean。

我是否遗漏了有关 Spring Boot 配置的内容?

(这种动态事务管理方法是通过引用博客 http://blog.tirasa.net/dynamic-springs--at-transactional.html 获得的)

最佳答案

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

最终代码的形式为 -

事务拦截器类

@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);
       }
   }
}

关于java - Spring Boot TransactionManager动态选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51087660/

相关文章:

spring-data-jpa - 处理事务中的 spring-data-rest 应用程序事件

java - 从 jar 运行主类的 Shell 命令

java - 拆分 LinkedList 对象

java - 在 jackson 中禁用数字到字符串的自动转换

java - Spring事务抛出异常后不回滚

java - @Transactional 注解的替代方案

java - Print Treeset<CustomClass> 返回奇怪的打印结果?

java - 由于没有重新粉刷,灰色启动画面

java - Spring安全,注销: Pass parameter from/logout to/login

spring-boot - 使用Kotlin和Gradle时如何将额外的spring-configuration-metadata.json与kapt合并?