我正在将现有的 Spring 应用程序转换为 Spring Boot 应用程序。在我现有的应用程序中,我们需要连接到多个数据库,我们通过定义多个数据源并根据条件获取相应的 bean 来实现这一点。还使用 TransactionInterceptor 的自定义实现来选择事务管理器。
@Override
public TransactionAttributeSource getTransactionAttributeSource() {
final TransactionAttributeSource origTxAttrSource = super.getTransactionAttributeSource();
return new TransactionAttributeSource() {
@Override
public TransactionAttribute getTransactionAttribute(final Method method, final Class<?> targetClass) {
TransactionAttribute txAttr = origTxAttrSource.getTransactionAttribute(method, targetClass);
String database = (String) ThreadContext.get("database");
if (database != null && StringUtils.isNotBlank(database)) {
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setQualifier("txManager" + database);
}
}
return txAttr;
}
};
}
通过 BeanFactoryPostProcessor
我们包含了这个拦截器
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] names = beanFactory.getBeanNamesForType(TransactionInterceptor.class);
for (String name : names) {
BeanDefinition bd = beanFactory.getBeanDefinition(name);
bd.setBeanClassName(MyTransactionInterceptor.class.getName());
}
}
这在 Spring 4.X 中运行得非常好。
现在我们正在转向 Spring Boot,我正在尝试转换相同的方法。我可以看到 Bean 工厂正在被调用,但我没有发现自定义拦截器类发生调用。这会导致我的 @Transactional
失败,因为有多个符合条件的 bean。
我是否遗漏了有关 Spring Boot 配置的内容?
(这种动态事务管理方法是通过引用博客 http://blog.tirasa.net/dynamic-springs--at-transactional.html 获得的)
最佳答案
最终的答案是将工厂类和工厂 bean 名称设置为 null,这会导致调用事务拦截器。我还没有弄清楚这如何影响拦截器调用以及这些字段中的值(它们指向 ProxyTransaction 类,因为 transactionInterceptor bean 是由它创建的)。
最终代码的形式为 -
事务拦截器类
@Component
public class TransactionInterceptorReplacer implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory factory) throws BeansException {
String[] names = factory.getBeanNamesForType(TransactionInterceptor.class);
for (String name : names) {
BeanDefinition bd = factory.getBeanDefinition(name);
bd.setBeanClassName(MyTransactionInterceptor.class.getName());
bd.setFactoryBeanName(null);
bd.setFactoryMethodName(null);
}
}
}
关于java - Spring Boot TransactionManager动态选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51087660/