記一次工作中使用spring-boot-activemq的排錯經(jīng)歷

一. 問題描述

最近在使用新版本的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 就無法自動注入進來搂抒,如下所示:


2019032009243494.png

但是如果用老版本的spring boot(1.5.13.RELEASE)爽彤,同樣的配置下則沒有這個問題棒口。

經(jīng)過分析源碼捐迫,終于找到了這個問題的答案

二. 原因

對spring boot activemq的配置

  activemq:
    # 連接用戶名
    user: admin
    # 連接密碼
    password: admin
    # mq broker地址
    broker-url: tcp://192.168.1.49:61616
    pool:
      #啟用連接池
      enabled: true
      #連接池最大連接數(shù)
      max-connections: 20
      #空閑的連接過期時間酵紫,默認為30秒
      idle-timeout: 30000

在2.X版本中:

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);
        }
 
    }
 
}

由以上代碼可知亡鼠,當(dāng)配置文件中存在 "spring.activemq.pool.enabled=true" 時旭从,會使用 JmsPoolConnectionFactory稳强,但是這個類(org.messaginghub.pooled.jms.JmsPoolConnectionFactory)并不在activemq-pool這個依賴中,所以導(dǎo)致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;
        }
 
    }
 
}

當(dāng) "spring.activemq.pool.enabled=true" 這個配置項存在時鸽素,往spring容器中注入的是 PooledConnectionFactory 這個類褒繁,而這個類,在activemq-pool這個依賴中馍忽,因此棒坏,在1.5.13的版本中,可以依賴activemq-pool遭笋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坝冕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瓦呼,更是在濱河造成了極大的恐慌喂窟,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件央串,死亡現(xiàn)場離奇詭異磨澡,居然都是意外死亡,警方通過查閱死者的電腦和手機质和,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門稳摄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侦另,你說我怎么就攤上這事秩命∥竟玻” “怎么了褒傅?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵弃锐,是天一觀的道長。 經(jīng)常有香客問我殿托,道長霹菊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任支竹,我火速辦了婚禮旋廷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘礼搁。我一直安慰自己饶碘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布馒吴。 她就那樣靜靜地躺著扎运,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饮戳。 梳的紋絲不亂的頭發(fā)上豪治,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音扯罐,去河邊找鬼负拟。 笑死,一個胖子當(dāng)著我的面吹牛歹河,可吹牛的內(nèi)容都是我干的掩浙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼秸歧,長吁一口氣:“原來是場噩夢啊……” “哼厨姚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寥茫,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤遣蚀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后纱耻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芭梯,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年弄喘,在試婚紗的時候發(fā)現(xiàn)自己被綠了玖喘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蘑志,死狀恐怖累奈,靈堂內(nèi)的尸體忽然破棺而出贬派,到底是詐尸還是另有隱情,我是刑警寧澤澎媒,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布搞乏,位于F島的核電站,受9級特大地震影響戒努,放射性物質(zhì)發(fā)生泄漏请敦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一储玫、第九天 我趴在偏房一處隱蔽的房頂上張望侍筛。 院中可真熱鬧,春花似錦撒穷、人聲如沸匣椰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禽笑。三九已至,卻和暖如春齐媒,著一層夾襖步出監(jiān)牢的瞬間蒲每,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工喻括, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邀杏,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓唬血,卻偏偏與公主長得像望蜡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拷恨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355