记一次工作中使用spring-boot-activemq的排错经历
程序员文章站
2022-06-21 13:38:10
一. 问题描述最近在使用新版本的spring boot连接activeMQ时(2.1.1.RELEASE)遇到了一个问题:引入依赖后, org.springframework.boot spring-boot-starter-parent 2.1.1.RELEASE
一. 问题描述
最近在使用新版本的spring boot连接activeMQ时(2.1.1.RELEASE)遇到了一个问题:引入依赖后,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
</dependencies>
如果开启activemq的连接池,则 JmsTemplate 就无法自动注入进来,如下所示:
但是如果用老版本的spring boot(1.5.13.RELEASE),同样的配置下则没有这个问题。
经过分析源码,终于找到了这个问题的答案,原因如下所示:
二. 原因
对spring boot activemq的配置:
spring.activemq.broker-url=failover:(tcp://ip1:port1,tcp://ip2:port2)?nested.wireFormat.maxInactivityDuration=1000
spring.activemq.in-memory=false
# true表示使用连接池
spring.activemq.pool.enabled=true
# 连接池的最大连接数
spring.activemq.pool.max-connections=5
# 空闲的连接过期时间,默认为30s
spring.activemq.pool.idle-timeout=30000
在2.1.1版本中:
package org.springframework.boot.autoconfigure.jms.activemq;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
/**
* Configuration for ActiveMQ {@link ConnectionFactory}.
*
* @author Greg Turnquist
* @author Stephane Nicoll
* @author Phillip Webb
* @author Andy Wilkinson
* @author Aurélien Leboulanger
* @since 1.1.0
*/
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
class ActiveMQConnectionFactoryConfiguration {
@Configuration
@ConditionalOnClass(CachingConnectionFactory.class)
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true)
static class SimpleConnectionFactoryConfiguration {
private final JmsProperties jmsProperties;
private final ActiveMQProperties properties;
private final List<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers;
SimpleConnectionFactoryConfiguration(JmsProperties jmsProperties,
ActiveMQProperties properties,
ObjectProvider<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers) {
this.jmsProperties = jmsProperties;
this.properties = properties;
this.connectionFactoryCustomizers = connectionFactoryCustomizers
.orderedStream().collect(Collectors.toList());
}
@Bean
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "true", matchIfMissing = true)
public CachingConnectionFactory cachingJmsConnectionFactory() {
JmsProperties.Cache cacheProperties = this.jmsProperties.getCache();
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(
createConnectionFactory());
connectionFactory.setCacheConsumers(cacheProperties.isConsumers());
connectionFactory.setCacheProducers(cacheProperties.isProducers());
connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize());
return connectionFactory;
}
@Bean
@ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false")
public ActiveMQConnectionFactory jmsConnectionFactory() {
return createConnectionFactory();
}
private ActiveMQConnectionFactory createConnectionFactory() {
return new ActiveMQConnectionFactoryFactory(this.properties,
this.connectionFactoryCustomizers)
.createConnectionFactory(ActiveMQConnectionFactory.class);
}
}
@Configuration
@ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class })
static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
public JmsPoolConnectionFactory pooledJmsConnectionFactory(
ActiveMQProperties properties,
ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory(
properties,
factoryCustomizers.orderedStream().collect(Collectors.toList()))
.createConnectionFactory(ActiveMQConnectionFactory.class);
return new JmsPoolConnectionFactoryFactory(properties.getPool())
.createPooledConnectionFactory(connectionFactory);
}
}
}
由以上代码可知,当配置文件中存在 spring.activemq.pool.enabled=true
时,会使用 JmsPoolConnectionFactory,但是这个类(org.messaginghub.pooled.jms.JmsPoolConnectionFactory
)并不在activemq-pool这个依赖中,所以导致ConnectionFactory无法注入,因此 JmsTemplate也就无法由Spring容器来管理。因此需要引入别的依赖,如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
</dependency>
而在1.5.13版本中
package org.springframework.boot.autoconfigure.jms.activemq;
import org.apache.activemq.pool.PooledConnectionFactory;
/**
* Configuration for ActiveMQ {@link ConnectionFactory}.
*
* @author Greg Turnquist
* @author Stephane Nicoll
* @author Phillip Webb
* @author Andy Wilkinson
* @author Aurélien Leboulanger
* @since 1.1.0
*/
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
class ActiveMQConnectionFactoryConfiguration {
@Bean
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true)
public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
return new ActiveMQConnectionFactoryFactory(properties,
factoryCustomizers.getIfAvailable())
.createConnectionFactory(ActiveMQConnectionFactory.class);
}
@Configuration
@ConditionalOnClass(PooledConnectionFactory.class)
static class PooledConnectionFactoryConfiguration {
@Bean(destroyMethod = "stop")
@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
@ConfigurationProperties(prefix = "spring.activemq.pool.configuration")
public PooledConnectionFactory pooledJmsConnectionFactory(
ActiveMQProperties properties,
ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(
new ActiveMQConnectionFactoryFactory(properties,
factoryCustomizers.getIfAvailable()).createConnectionFactory(
ActiveMQConnectionFactory.class));
ActiveMQProperties.Pool pool = properties.getPool();
pooledConnectionFactory.setBlockIfSessionPoolIsFull(pool.isBlockIfFull());
pooledConnectionFactory
.setBlockIfSessionPoolIsFullTimeout(pool.getBlockIfFullTimeout());
pooledConnectionFactory
.setCreateConnectionOnStartup(pool.isCreateConnectionOnStartup());
pooledConnectionFactory.setExpiryTimeout(pool.getExpiryTimeout());
pooledConnectionFactory.setIdleTimeout(pool.getIdleTimeout());
pooledConnectionFactory.setMaxConnections(pool.getMaxConnections());
pooledConnectionFactory.setMaximumActiveSessionPerConnection(
pool.getMaximumActiveSessionPerConnection());
pooledConnectionFactory
.setReconnectOnException(pool.isReconnectOnException());
pooledConnectionFactory.setTimeBetweenExpirationCheckMillis(
pool.getTimeBetweenExpirationCheck());
pooledConnectionFactory
.setUseAnonymousProducers(pool.isUseAnonymousProducers());
return pooledConnectionFactory;
}
}
}
当 spring.activemq.pool.enabled=true
这个配置项存在时,往spring容器中注入的是 PooledConnectionFactory 这个类,而这个类,在activemq-pool这个依赖中,因此,在1.5.13的版本中,可以依赖activemq-pool:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
本文地址:https://blog.csdn.net/hermi0ne/article/details/107389022