我想配置" transactional"来自我的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");
}
我想在配置类中做什么(以及哪些不能在我的单元测试中工作):
@Configuration
@EnableTransactionManagement
public class ComplexComponentConfig {
@Bean
@Transactional // <- Make the bean transactional here
public ComplexComponent complexComponent() {
return new ComplexComponentImpl(repository());
}
// ...
}
上面的例子实际上并没有起作用,因为没有任何事情可以解决问题&#34;事务性的&#34;在运行时:即使抛出异常,实体e1
也会被持久化。
请注意,我的事务管理设置适用于标有@Transactional
的实现类。
问题:是否可以从@Bean
类声明@Configuration
的事务处理,或者是否有任何其他方法考虑上述约束?
答案 0 :(得分: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;
}
// ...
}
答案 1 :(得分:1)
我认为你可能不会以这种方式使用@Transactional。 Spring的内置PostProcessors之一,应该扫描具有该注释的所有类(bean),并相应地创建Aspects。
关于替代方案:我会为每个必须使用的第三方类编写一个Adapter类。然后使这些Adapter类成为Spring Beans。
答案 2 :(得分:1)
您不能以这种方式使用@Transactional
,但您可以使用Spring以编程方式配置方面。
用于以编程方式定义方面的Spring文档:
文档中的示例非常简单。定义事务方面可能会更复杂,如果您发现使用基于XML的代理的便利性或者采用@Mecon的建议并编写适配器,我不会感到惊讶。