当前位置: 移动技术网 > IT编程>开发语言>Java > 记一次工作中使用spring-boot-activemq的排错经历

记一次工作中使用spring-boot-activemq的排错经历

2020年07月17日  | 移动技术网IT编程  | 我要评论
一. 问题描述最近在使用新版本的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

一. 问题描述

最近在使用新版本的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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网