spring boot2.0整合activeMQ,配置连接池,启动项目报错,JmsMessagingTemplate无法注入

上一篇讲到在整合activeMQ如何将queue和topic两种模式共存:spring boot2.0整合activeMQ,实现p2p和topic两者消息模式兼容共存
然后还遗留了一个问题,有读者评论因为配置文件里一句启用连接池导致项目启动报错,只要把那句配置注释掉或者改为false就可以了,这实际上是治标不治本,因毕竟流量大的时候不启用连接池效率会很低:

# 启用连接池
spring.activemq.pool.enabled=true

诚然,如果不想使用连接池,那么快速的办法的确是把这个配置直接干掉,或者改为false,其是默认就是false,但是我们来看一看启用连接池后启动项目提示JmsMessagingTemplate无法注入真正的原因是什么

开启连接池,启动项目会报错,提示JmsMessagingTemplate无法注入、

目前使用springboot最新版本是2.1+,我先直接告诉你解决方法,如果要启用连接池:

  • 使用springboot2.0+及以下版本时候,maven配置依赖是:
<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-pool</artifactId>
</dependency>
  • 使用springboot2.1+时候,maven配置依赖是:
<dependency>
    <groupId>org.messaginghub</groupId>
    <artifactId>pooled-jms</artifactId>
</dependency>

请按照自己使用的springboot版本更换对应的连接池依赖就可以解决问题。但为什么一样呢?我们来看看springboot的自动配置的部分源码:

  • 使用springboot2.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)
        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());
            if (pool.getBlockIfFullTimeout() != null) {
                pooledConnectionFactory.setBlockIfSessionPoolIsFullTimeout(
                        pool.getBlockIfFullTimeout().toMillis());
            }
            pooledConnectionFactory
                    .setCreateConnectionOnStartup(pool.isCreateConnectionOnStartup());
            if (pool.getExpiryTimeout() != null) {
                pooledConnectionFactory
                        .setExpiryTimeout(pool.getExpiryTimeout().toMillis());
            }
            if (pool.getIdleTimeout() != null) {
                pooledConnectionFactory
                        .setIdleTimeout((int) pool.getIdleTimeout().toMillis());
            }
            pooledConnectionFactory.setMaxConnections(pool.getMaxConnections());
            pooledConnectionFactory.setMaximumActiveSessionPerConnection(
                    pool.getMaximumActiveSessionPerConnection());
            pooledConnectionFactory
                    .setReconnectOnException(pool.isReconnectOnException());
            if (pool.getTimeBetweenExpirationCheck() != null) {
                pooledConnectionFactory.setTimeBetweenExpirationCheckMillis(
                        pool.getTimeBetweenExpirationCheck().toMillis());
            }
            pooledConnectionFactory
                    .setUseAnonymousProducers(pool.isUseAnonymousProducers());
            return pooledConnectionFactory;
        }

    }

}
  • 使用springboot2.1+时候,maven配置依赖是:
@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);
        }

    }

}

很明显我们看的出来,2.1和2.0以下版本使用连接池时候的连接池对象不一样:

  • 2.0+以下版本使用的是PooledConnectionFactory,它存在于org.apache.activemq.pool.PooledConnectionFactory
  • 2.1+版本使用的是JmsPoolConnectionFactory,它存在于org.messaginghub.pooled.jms.JmsPoolConnectionFactory

由此我们就明白了为什么更换连接池依赖就ok,因为JmsMessagingTemplate本身依赖连接工厂,启用连接池后就会依赖连接池工厂,因为版本的原因,如果没有正确的引入连接池依赖,那么必定会出现文章一开头说的,项目启动报错:JmsMessagingTemplate无法注入

最后在提醒一下注意源码中的注解:

@ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)

当前缀为:spring.activemq.pool 的配置的属性:enabled的值为:true 的时候就会实例化bean,如果没有正确引入连接池依赖就会报错。

猜你喜欢

转载自blog.csdn.net/eumenides_/article/details/91850332