Spring 从配置 java 文件中禁用 @Transactional

问题描述 投票:0回答:1

我有一个在两个不同应用程序中使用的代码库。一些Spring服务类有@Transactional注解。在服务器启动时,我想根据某些配置禁用@Transactional。

以下是我的配置类。

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.properties")

public class WebAppConfig {

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";

    @Resource
    private Environment env;
    
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        dataSource.setUrl(url);
        dataSource.setUsername(userId);
        dataSource.setPassword(password);

        return dataSource;
    }
    @Bean
    public PlatformTransactionManager txManager() {
         DefaultTransactionDefinition def = new DefaultTransactionDefinition();
         def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
            if(appName.equqls("ABC")) {
                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
                }else {
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                }
         CustomDataSourceTransactionManager txM=new CustomDataSourceTransactionManager(def);
         txM.setDataSource(dataSource());
    return txM;
    }
    

    @Bean
    public JdbcTemplate jdbcTemplate() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }
    
}

我尝试重写 DataSourceTransactionManager 中的方法来实现该功能,但它仍然尝试在事务结束时提交/回滚事务。由于没有可用的数据库连接,它会抛出异常。

如果我保留 @Transactional(propagation=Propagation.NEVER),一切都会完美运行,但我无法修改它,因为另一个应用程序正在使用相同的代码库,在这种情况下这是必要的。

我想知道是否有一种方法可以在不修改@Transactional注释的情况下使事务完全从配置中禁用。

spring spring-jdbc spring-transactions
1个回答
3
投票

我不确定它是否有效,但您可以尝试实现自定义

TransactionInterceptor
并通过删除事务性内容来重写将调用包装到事务中的方法。像这样的东西:

public class NoOpTransactionInterceptor extends TransactionInterceptor {

    @Override
    protected Object invokeWithinTransaction(
        Method method, 
        Class<?> targetClass, 
        InvocationCallback invocation
    ) throws Throwable {
        // Simply invoke the original unwrapped code
        return invocation.proceedWithInvocation();
    }
}

然后在

@Configuration
类之一中声明一个条件 bean

// assuming this property is stored in Spring application properties file
@ConditionalOnProperty(name = "turnOffTransactions", havingValue = "true")) 
@Bean   
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
         /* default bean would be injected here */
         TransactionAttributeSource transactionAttributeSource
) {
    TransactionInterceptor interceptor = new NoOpTransactionInterceptor();
    interceptor.setTransactionAttributeSource(transactionAttributeSource);
    return interceptor;
}

可能您需要额外的配置,我现在无法验证

© www.soinside.com 2019 - 2024. All rights reserved.