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

在集成测试期间,我需要忽略以下@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)
    }

}

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

最佳答案 首先,您需要将当前的@EnableTransactionManagement注释排除在测试配置文件中.您可以通过将@EnableTransactionManagement批注隔离到单独的配置类来完成此操作,该配置类排除了配置文件测试,因此只有在测试配置文件不活动时才会激活它.

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

最后,您将能够覆盖事务属性的部分.这个为AdviceMode.PROXY的ProxyTransactionManagementConfiguration子类,您需要一个基于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;
            }
        };
    }
}

最后,您需要使用与测试配置文件绑定的配置类启用自定义事务管理配置.

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

我希望这有帮助.

点赞