我正在将现有的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工厂,但是没有发现Custom Interceptor类正在发生调用。这导致我的@Transactional
失败,因为有多个合格的bean。
我是否缺少有关Spring Boot配置的信息?
(这种动态交易管理的方法是通过参考博客http://blog.tirasa.net/dynamic-springs--at-transactional.html)
答案 0 :(得分:2)
最终的答案是将工厂类和工厂bean名称设置为null,这导致事务拦截器被调用。我还没有弄清楚这将如何影响这些拦截器的调用(与这些字段中的值一样)(它们指向ProxyTransaction类,因为它是由transactionInterceptor bean创建的)。
最终代码的格式为-
TransactionInterceptor类
@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);
}
}
}