我正在使用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监听器工作正常.但是,当我尝试在方法中使用我的存储库(Spring Data JPA)来保存数据时@Transactional
,我得到以下异常:
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 放在应该是默认值的bean之上.但是,在这种情况下,我使用Spring启动的自动配置,所以我无法添加@Primary
它.
另一种解决方案是使用每个@Transactional
注释提供事务管理器的名称(例如@Transactional("transactionManager")
,但这将是很多工作,因为JMS事务管理器是一种特殊情况,因此拥有默认事务管理器会更有意义.
是否有一种简单的方法来定义默认使用的自动配置的事务管理器?
Spring引导'魔术'实际上只是这样:
@Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) public PlatformTransactionManager transactionManager() { return new JpaTransactionManager(); }
在org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration
课堂上.
注意@ConditionalOnMissingBean
注释 - 只有在类型的bean PlatformTransactionManager
不存在时才会配置注释.因此,您可以通过使用@Primary
注释创建自己的bean来覆盖它:
@Bean @Primary public PlatformTransactionManager transactionManager() { return new JpaTransactionManager(); }