java - 当@ActiveProfiles ("test"时,如何忽略特定方法的 spring @Transactional 注释)

标签 java spring spring-transactions

我需要在集成测试期间忽略以下 @Transactional 注释。

@Service
public class MyClass {

    @Transactional(propagation = Propagation.NEVER)
    public void doSomething() {
        // do something that once in production can not be inside a transaction (reasons are omitted)
    }

}

问题是我所有的测试都是在默认情况下回滚的事务中执行的。当此方法在测试范围内运行时,我怎么能忽略此方法的 @Transactional(propagation = Propagation.NEVER) 注释 (@ActiveProfiles("test") ) 允许它在事务内执行?

最佳答案

首先,你需要排除你当前的@EnableTransactionManagement注释在您的 test 中处于 Activity 状态轮廓。您可以通过隔离 @EnableTransactionManagement 来做到这一点对排除配置文件 test 的单独配置类的注释所以它只会在 test 时被激活配置文件有效。

@EnableTransactionManagement(mode=AdviceMode.PROXY)
@Profile("!test")
public class TransactionManagementConfig {}

有了这些,我们就可以开始为您的测试配置文件构建自定义事务管理配置。首先,我们定义一个注释,将用于激活自定义事务管理(为了示例的紧凑性而删除了 javadoc 注释,有关详细信息,请参阅 EnableTransactionManagement javadoc)。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CustomTransactionManagementConfigurationSelector.class)
public @interface EnableCustomTransactionManagement {
    boolean proxyTargetClass() default false;
    AdviceMode mode() default AdviceMode.PROXY;
    int order() default Ordered.LOWEST_PRECEDENCE;
}

然后我们需要一个导入选择器。请注意,因为您使用的是 AdviceMode.PROXY ,我跳过了实现 ASPECTJ部分,但为了使用基于 AspectJ 的事务管理,应该类似地完成。

public class CustomTransactionManagementConfigurationSelector extends
        AdviceModeImportSelector<EnableCustomTransactionManagement> {
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
        case PROXY:
            return new String[] { 
                AutoProxyRegistrar.class.getName(),
                CustomTransactionAttributeSourceConfig.class.getName()
            };
        case ASPECTJ:
        default:
            return null;
        }
    }
}

最后是您可以覆盖交易属性的部分。这一个子类 ProxyTransactionManagementConfiguration对于 AdviceMode.PROXY , 你需要一个基于 AspectJTransactionManagementConfiguration 的类似实现对于 AdviceMode.ASPECTJ .随意实现您自己的逻辑,无论是对原始 AnnotationTransactionAttributeSource 的任何属性的常量覆盖将按照我的示例进行确定,或者通过为此目的引入和处理您自己的自定义注释来进行更深入的研究。

@Configuration
public class CustomTransactionAttributeSourceConfig
        extends ProxyTransactionManagementConfiguration {

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        this.enableTx = AnnotationAttributes
                .fromMap(importMetadata.getAnnotationAttributes(
                        EnableCustomTransactionManagement.class.getName(),
                        false));
        Assert.notNull(this.enableTx,
                "@EnableCustomTransactionManagement is not present on importing class "
                        + importMetadata.getClassName());
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Override
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource() {

            private static final long serialVersionUID = 1L;

            @Override
            protected TransactionAttribute findTransactionAttribute(
                    Class<?> clazz) {
                TransactionAttribute transactionAttribute = 
                        super.findTransactionAttribute(clazz);
                if (transactionAttribute != null) {
                    // implement whatever logic to override transaction attributes 
                    // extracted from @Transactional annotation
                    transactionAttribute = new DefaultTransactionAttribute(
                            TransactionAttribute.PROPAGATION_REQUIRED);
                }
                return transactionAttribute;
            }

            @Override
            protected TransactionAttribute findTransactionAttribute(
                    Method method) {
                TransactionAttribute transactionAttribute = 
                        super.findTransactionAttribute(method);
                if (transactionAttribute != null) {
                    // implement whatever logic to override transaction attributes
                    // extracted from @Transactional annotation
                    transactionAttribute = new DefaultTransactionAttribute(
                            TransactionAttribute.PROPAGATION_REQUIRED);
                }
                return transactionAttribute;
            }
        };
    }
}

最后,您需要使用绑定(bind)到 test 的配置类来启用自定义事务管理配置。简介。

@EnableCustomTransactionManagement(mode=AdviceMode.PROXY)
@Profile("test")
public class TransactionManagementTestConfig {}

希望对您有所帮助。

关于java - 当@ActiveProfiles ("test"时,如何忽略特定方法的 spring @Transactional 注释),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35902955/

相关文章:

java - 在Java中解析远程文件的FLV头(持续时间)

java - 按降序显示文件中出现次数最多的 10 个单词

java - 动态添加 TextView 到布局

java - CXF 使用的类中的公共(public)方法上的@Transactional 问题

java - 如何在项目 react 器中组合来自两个 react 流的数据?

spring - Hibernate - 更新后表锁定

Spring 3、TransactionManagement、Tomcat 和更改数据源 midflight

java - JPA后台缓存刷新

java - 如何验证 Spring + AspecJ 事务?

java - Spring数据库事务未在Db中提交数据