Spring @Transactional on @Bean声明而不是类Implementation

Mic*_*urt 7 java spring jpa transactions

我想从我的Spring @Configuration类配置"事务性"bean,而不是使用它来注释类实现本身@Transactional.

有点像旧学校的方式,从XML文件配置事务建议,但不需要对我的类/方法名称的String引用来创建切入点.

原因是bean实现在另一个代码库中,它所属的模块不依赖于Spring.阅读:我没有触及那个bean的源代码,只是实例化它.该类是final,无法扩展它以将Spring注释添加到子类.假设所有方法都必须是事务性的,为简单起见.

bean实现:

/** This class has no Spring dependency... */
// @Transactional <- which means I can't use this here
public final class ComplexComponentImpl implements ComplexComponent {

    private SomeRepository repo;

    public ComplexComponentImpl(SomeRepository repository) { this.repo = repository }

    public void saveEntities(SomeEntity e1, SomeEntity e2) {
        repo.save(e1);
        throw new IllegalStateException("Make the transaction fail");
    }
Run Code Online (Sandbox Code Playgroud)

我想在我的配置类中做什么(哪些在我的单元测试中不起作用):

@Configuration
@EnableTransactionManagement
public class ComplexComponentConfig {

    @Bean
    @Transactional // <- Make the bean transactional here
    public ComplexComponent complexComponent() {
        return new ComplexComponentImpl(repository());
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

事实上,上面的例子不起作用,因为在运行时没有任何东西变成"事务性":e1即使抛出异常,实体也会被持久化.

请注意,我的事务管理设置与标记为的实现类完美配合@Transactional.

问题:是否可以@Bean@Configuration类中声明s事务,或者是否有任何替代方案考虑上述约束?

Mic*_*urt 8

找到了内置的东西,这是@Mecon@Erik Gillespie的答案的总和,有限的样板.

Spring已经提供了一个TransactionProxyFactoryBean只在任何对象上设置事务代理的方法.许多设置可以重构为一些实用方法:

@Configuration
@EnableTransactionManagement
public class ComplexComponentConfig {

    /** NOT A @Bean, this object will be wrapped with a transactional proxy */
    public ComplexComponent complexComponentImpl() {
        return new ComplexComponentImpl(repository());
    }

    @Bean
    public ComplexComponent complexComponent() {
        TransactionProxyFactoryBean proxy = new TransactionProxyFactoryBean();

        // Inject transaction manager here
        proxy.setTransactionManager(txManager());

        // Define wich object instance is to be proxied (your bean)
        proxy.setTarget(complexComponentImpl());

        // Programmatically setup transaction attributes
        Properties transactionAttributes = new Properties();
        transactionAttributes.put("*", "PROPAGATION_REQUIRED");
        proxy.setTransactionAttributes(transactionAttributes);

        // Finish FactoryBean setup
        proxy.afterPropertiesSet();
        return (ComplexComponent) proxy.getObject;
    }

// ...
}
Run Code Online (Sandbox Code Playgroud)