Spring原始碼分析之spring-jms模組詳解

內聖外王發表於2015-04-27

0 概述

spring提供了一個jms整合框架,這個框架如spring 整合jdbc api一樣,簡化了jms api的使用。

jms可以簡單的分成兩個功能區,訊息的生產和訊息的消費。JmsTemplate類用來生成訊息和同步接受訊息。和其它java ee的訊息驅動樣式一樣,對非同步訊息,spring也提供了許多訊息監聽容器用來建立訊息驅動的POJO(MDPs)。spring同時也提供了建立訊息監聽器的宣告方式。

org.springframework.jms.core 提供了使用JMS的核心功能,它包含JmsTemplate類,該類類似於jdbc中的jdbdTemplate,它通過對資源的建立和釋放處理來簡化jms開發。spring的模板類作為一種設計原則在spring框架中廣泛使用,模板類對簡單操作提供了幫助方法;對複雜操作,通過繼承回撥介面提供了重要處理過程的代理。jmsTemplate同樣遵循這一設計原則,它提供了傳送訊息、同步消費訊息、為使用者提供JMS session和訊息生產者的多種便利方法。

org.springframework.jms.support提供了JmsException轉譯功能。它將checked的JmsException層次轉換成uncheckedd異常的映象層次。若丟擲的異常不是javax.jms.JmsException的子類,這個異常將被封裝成unchecked異常UncategorizedJmsException。

org.springframework.jms.support.converter 提供了在java物件和jms訊息之間轉換的抽象MessageConverter。

org.springframework.jms.support.destination提供了管理jms destination的多種策略,如對存放在jndi的destionation提供服務定位功能。

org.springframework.jms.annotation通過使用@JmsListener提供了對註解驅動的監聽端的支援。

org.springframework.jms.config 支援jms名稱空間的解析,同時也支援配置監聽容器和生成監聽端。

最後,org.springframework.jms.connection提供了適用於standonle應用的ConnectionFactory的實現。它也了spring PlatFormTransactionManager對jms的事務管理實現jmsTranscationmanager. 這允許jms 作為事務資源無縫的整合到Spring事務管理機制中。

1. 異常處理類模組

異常的轉換在JmsUtils中來做的:

/**
     * Convert the specified checked {@link javax.jms.JMSException JMSException} to a
     * Spring runtime {@link org.springframework.jms.JmsException JmsException} equivalent.
     * @param ex the original checked JMSException to convert
     * @return the Spring runtime JmsException wrapping the given exception
     */
    public static JmsException convertJmsAccessException(JMSException ex) {
        Assert.notNull(ex, "JMSException must not be null");

        if (ex instanceof javax.jms.IllegalStateException) {
            return new org.springframework.jms.IllegalStateException((javax.jms.IllegalStateException) ex);
        }
        if (ex instanceof javax.jms.InvalidClientIDException) {
            return new InvalidClientIDException((javax.jms.InvalidClientIDException) ex);
        }
        if (ex instanceof javax.jms.InvalidDestinationException) {
            return new InvalidDestinationException((javax.jms.InvalidDestinationException) ex);
        }
        if (ex instanceof javax.jms.InvalidSelectorException) {
            return new InvalidSelectorException((javax.jms.InvalidSelectorException) ex);
        }
        if (ex instanceof javax.jms.JMSSecurityException) {
            return new JmsSecurityException((javax.jms.JMSSecurityException) ex);
        }
        if (ex instanceof javax.jms.MessageEOFException) {
            return new MessageEOFException((javax.jms.MessageEOFException) ex);
        }
        if (ex instanceof javax.jms.MessageFormatException) {
            return new MessageFormatException((javax.jms.MessageFormatException) ex);
        }
        if (ex instanceof javax.jms.MessageNotReadableException) {
            return new MessageNotReadableException((javax.jms.MessageNotReadableException) ex);
        }
        if (ex instanceof javax.jms.MessageNotWriteableException) {
            return new MessageNotWriteableException((javax.jms.MessageNotWriteableException) ex);
        }
        if (ex instanceof javax.jms.ResourceAllocationException) {
            return new ResourceAllocationException((javax.jms.ResourceAllocationException) ex);
        }
        if (ex instanceof javax.jms.TransactionInProgressException) {
            return new TransactionInProgressException((javax.jms.TransactionInProgressException) ex);
        }
        if (ex instanceof javax.jms.TransactionRolledBackException) {
            return new TransactionRolledBackException((javax.jms.TransactionRolledBackException) ex);
        }

        // fallback
        return new UncategorizedJmsException(ex);
    }

2. config模組

支援jms名稱空間的解析,同時也支援配置監聽容器和生成監聽端。其結構如下:

其中,在JmsNamespaceHandler中使用到了監聽容器,如下:

public class JmsNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("listener-container", new JmsListenerContainerParser());
        registerBeanDefinitionParser("jca-listener-container", new JcaListenerContainerParser());
    }

}

3. connection模組

提供了適用於standonle應用的ConnectionFactory的實現。它也了spring PlatFormTransactionManager對jms的事務管理實現jmsTranscationmanager. 這允許jms 作為事務資源無縫的整合到spring事務管理機制中。其結構如下:

JmsTemplate需要一個ConnectionFactory的引用,ConnectionFactory作為jsm規範的一部分,是作為和jms互動中一個關鍵因素,用來作為工廠建立和jms 提供者連線客戶端應用的connection,並且封裝了多種型別的配置引數,這些引數一般由jsm 提供者指明,例如ssl 配置選項。

SingleConnectionFactory 建立連線時返回同一個連線Connectin而忽略了close()呼叫。它適用於測試環境和standalone環境,因為相同的connection可以被多個JmsTemplate呼叫,這些呼叫可以跨越多個事務。SingleConnectionFactory有一個可能來自於jndi的標準ConnectionFactory引用。

CachingConnectionFactory擴充套件了SingleConnectionFactory的功能,增加了session的快取,MessageProducer和messageConsumer。快取的初始化size設定為1,使用

4. core模組

提供了使用JMS的核心功能。

使用jmsTemplate時只需要繼承callback介面,通過繼承call介面可以定義一個高階別的協議,MessageCreator callback介面在指定session建立一個訊息,它只可以被JmsTemplate呼叫。為滿足更jms api更復雜的應用,SessionCallBack給使用者提供了jms session,ProducerCallback暴露了session和messageProducer兩個。

jms api提供兩種型別的send方法,一種設定delivery模式,優先順序,存活時間(time-to-live)作為qos引數,另一種不提供qos引數而使用預設值。

5. Listener模組

訊息監聽容器(MessageListenerContainer)用來從jms 訊息佇列中接受訊息,然後推送註冊到它內部的訊息監聽器(MessageListener)中。spring提供了兩種標準的jms 訊息監聽容器,特色如下:

SimpleMessageListenerContainer:在啟動時,建立固定數目的jms 會話和一個消費者,使用標準的jms     MessageConsumer.setMessageListener()方法來註冊監聽器,讓jms 提供者來讓監聽器返回。

DefaultMessageListenerContainer:支援在執行時動態適應,並且能參與到外部受管理事務。每個接收到的訊息使用JtaTransactionManager註冊為XA 事務,因而可以充分利用xa 事務語義進行處理。

6. remoting模組

org.aopalliance.intercept.MethodInterceptor 用來接收基於jms的遠端服務。

JmsInvokerClientInterceptor:序列化遠端觸發物件和反序列化遠端觸發結果物件,使用java序列化方法,例如RMI.

JmsInvokerProxyFactoryBean:jms觸發代理的工廠bean,暴露bean引用的代理服務,使用特定的服務介面。

JmsInvokerServiceExporter:jms訊息監聽器,暴露特定服務bean作為jsm訊息的終端,通過jms 觸發代理獲取之。

小結

spring提供了一個jms整合框架,這個框架如spring 整合jdbc api一樣,簡化了jms api的使用。

相關文章