多个事务管理器 NoUniqueBeanDefinitionException
Multiple transaction managers NoUniqueBeanDefinitionException
我正在使用 Spring 启动并且我定义了 spring.datasource.*
属性来启用我的数据源。如果我只使用它,它就可以正常工作。但是,我现在也尝试使用以下配置将 JMS 添加到我的应用程序中:
@Configuration
@EnableJms
public class TriggerQueueConfig {
private Logger logger = LoggerFactory.getLogger(getClass());
@Value("${jms.host:localhost}")
private String host;
@Value("${jms.port:1414}")
private int port;
@Value("${jms.concurrency.min:3}-${jms.concurrency.max:10}")
private String concurrency;
@Value("${jms.manager}")
private String queueManager;
@Value("${jms.cache:100}")
private int cacheSize;
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory() throws JMSException {
logger.debug("Setting queue concurrency to {} (min-max)", concurrency);
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(cachedConnectionFactory());
factory.setMessageConverter(messageConverter());
factory.setTransactionManager(transactionManager());
factory.setSessionTransacted(true);
factory.setConcurrency(concurrency);
return factory;
}
@Bean(name = "jmsTransactionManager")
public JmsTransactionManager transactionManager() throws JMSException {
JmsTransactionManager transactionManager = new JmsTransactionManager();
transactionManager.setConnectionFactory(cachedConnectionFactory());
return transactionManager;
}
@Bean
@Primary
public ConnectionFactory cachedConnectionFactory() throws JMSException {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(ibmConnectionFactory());
connectionFactory.setSessionCacheSize(cacheSize);
connectionFactory.setCacheConsumers(true);
return connectionFactory;
}
@Bean
public ConnectionFactory ibmConnectionFactory() throws JMSException {
logger.debug("Connecting to queue on {}:{}", host, port);
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setHostName(host);
connectionFactory.setPort(port);
connectionFactory.setQueueManager(queueManager);
connectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
return connectionFactory;
}
@Bean
public MessageConverter messageConverter() {
MarshallingMessageConverter converter = new MarshallingMessageConverter();
converter.setMarshaller(marshaller());
converter.setUnmarshaller(marshaller());
return converter;
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.example");
return marshaller;
}
}
我创建的 JMS 侦听器工作正常。但是,当我尝试在 @Transactional
方法中使用我的存储库 (Spring Data JPA) 保存数据时,出现以下异常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: transactionManager,jmsTransactionManager
这是有道理的,因为两个事务管理器都是 PlatformTransactionManager
的。通常你会把 @Primary
放在默认的 bean 之上。但是,在这种情况下,我使用的是 Spring 引导程序的自动配置,因此我无法在其上添加 @Primary
。
另一种解决方案是为每个 @Transactional
注释提供事务管理器的名称(例如 @Transactional("transactionManager")
,但这需要大量工作,而且更有意义有一个默认的事务管理器,因为 JMS 事务管理器是一个例外情况。
是否有一种简单的方法来定义默认使用的自动配置的事务管理器?
Spring开机'magic'真的只有这个:
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
在 org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration
class.
注意 @ConditionalOnMissingBean
注释 - 只有当 PlatformTransactionManager
类型的 bean 不存在时才会配置此注释。因此,您可以通过使用 @Primary
注释创建自己的 bean 来覆盖它:
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
我正在使用 Spring 启动并且我定义了 spring.datasource.*
属性来启用我的数据源。如果我只使用它,它就可以正常工作。但是,我现在也尝试使用以下配置将 JMS 添加到我的应用程序中:
@Configuration
@EnableJms
public class TriggerQueueConfig {
private Logger logger = LoggerFactory.getLogger(getClass());
@Value("${jms.host:localhost}")
private String host;
@Value("${jms.port:1414}")
private int port;
@Value("${jms.concurrency.min:3}-${jms.concurrency.max:10}")
private String concurrency;
@Value("${jms.manager}")
private String queueManager;
@Value("${jms.cache:100}")
private int cacheSize;
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory() throws JMSException {
logger.debug("Setting queue concurrency to {} (min-max)", concurrency);
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(cachedConnectionFactory());
factory.setMessageConverter(messageConverter());
factory.setTransactionManager(transactionManager());
factory.setSessionTransacted(true);
factory.setConcurrency(concurrency);
return factory;
}
@Bean(name = "jmsTransactionManager")
public JmsTransactionManager transactionManager() throws JMSException {
JmsTransactionManager transactionManager = new JmsTransactionManager();
transactionManager.setConnectionFactory(cachedConnectionFactory());
return transactionManager;
}
@Bean
@Primary
public ConnectionFactory cachedConnectionFactory() throws JMSException {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(ibmConnectionFactory());
connectionFactory.setSessionCacheSize(cacheSize);
connectionFactory.setCacheConsumers(true);
return connectionFactory;
}
@Bean
public ConnectionFactory ibmConnectionFactory() throws JMSException {
logger.debug("Connecting to queue on {}:{}", host, port);
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setHostName(host);
connectionFactory.setPort(port);
connectionFactory.setQueueManager(queueManager);
connectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
return connectionFactory;
}
@Bean
public MessageConverter messageConverter() {
MarshallingMessageConverter converter = new MarshallingMessageConverter();
converter.setMarshaller(marshaller());
converter.setUnmarshaller(marshaller());
return converter;
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.example");
return marshaller;
}
}
我创建的 JMS 侦听器工作正常。但是,当我尝试在 @Transactional
方法中使用我的存储库 (Spring Data JPA) 保存数据时,出现以下异常:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: transactionManager,jmsTransactionManager
这是有道理的,因为两个事务管理器都是 PlatformTransactionManager
的。通常你会把 @Primary
放在默认的 bean 之上。但是,在这种情况下,我使用的是 Spring 引导程序的自动配置,因此我无法在其上添加 @Primary
。
另一种解决方案是为每个 @Transactional
注释提供事务管理器的名称(例如 @Transactional("transactionManager")
,但这需要大量工作,而且更有意义有一个默认的事务管理器,因为 JMS 事务管理器是一个例外情况。
是否有一种简单的方法来定义默认使用的自动配置的事务管理器?
Spring开机'magic'真的只有这个:
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
在 org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration
class.
注意 @ConditionalOnMissingBean
注释 - 只有当 PlatformTransactionManager
类型的 bean 不存在时才会配置此注释。因此,您可以通过使用 @Primary
注释创建自己的 bean 来覆盖它:
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}