javascript
Spring----JmsTemplate
盡管消息接收可以使用消息監聽的方式替代模板方法,但是發送的時候是無法代替的,在Spring中必須要使用JmsTemplate提供的方法來進行發送操作,可見JmsTemplate類的重要性,那么我們對于整合消息服務的分析就從JmsTemplate開始。
JmsTemplate
在上一篇文章中,我們看到了Spring采用了與JDBC等一貫的套路,為我們提供了JmsTemplate來封裝常用操作。下面看一下它的類圖:
提取我們感興趣的接口InitializingBean,接口方法的實現是在JmsAccessor類中,如下:
public void afterPropertiesSet() {if (getConnectionFactory() == null) {throw new IllegalArgumentException("Property 'connectionFactory' is required");}}發現函數中只是一個驗證功能,并沒有邏輯實現。所以丟掉這里,轉向實例代碼分析。首先以發送為例,在Spring中發送消息可以通過JmsTemplate中提供的方法來實現。
public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException {execute(session -> {doSend(session, destination, messageCreator);return null;}, false);}這個函數的風格不得不讓我們回想起JdbcTemplate的類實現風格,極為相似,都是提取一個公共的方法作為最底層、最通用的功能實現,然后又通過回調函數的不同來區分個性化的功能。
我們首先查看通用代碼的抽取實現。
1.通用代碼抽取?
public <T> T execute(SessionCallback<T> action, boolean startConnection) throws JmsException {Assert.notNull(action, "Callback object must not be null");Connection conToClose = null;Session sessionToClose = null;try {Session sessionToUse = ConnectionFactoryUtils.doGetTransactionalSession(obtainConnectionFactory(), this.transactionalResourceFactory, startConnection);if (sessionToUse == null) {//創建connectionconToClose = createConnection();//創建sessionsessionToClose = createSession(conToClose);//是否開啟向服務器推送連接信息,只有接收消息時需要,發送時不需要if (startConnection) {conToClose.start();}sessionToUse = sessionToClose;}if (logger.isDebugEnabled()) {logger.debug("Executing callback on JMS Session: " + sessionToUse);}//調用回調函數return action.doInJms(sessionToUse);}catch (JMSException ex) {throw convertJmsAccessException(ex);}finally {//關閉session JmsUtils.closeSession(sessionToClose);//釋放連接 ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), startConnection);}}上述代碼封裝了connection以及session的創建操作。在準備工作結束后,調用回調函數將程序引入用戶自定義實現的個性化處理。
2.發送消息的實現
?有了基類的輔助實現,使得Spring更加專注于個性的處理,也就是說Spring使用execute方法中封裝了冗余代碼,而將個性化的代碼實現放在了回調函數doInJms中。在發送消息的功能中回調函數通過局部類實現。
execute(session -> {doSend(session, destination, messageCreator);return null;}, false);此時的發送邏輯已經完全轉向了doSend方法,這樣使整個功能實現變得更加清晰了。
protected void doSend(Session session, Destination destination, MessageCreator messageCreator)throws JMSException {Assert.notNull(messageCreator, "MessageCreator must not be null");MessageProducer producer = createProducer(session, destination);try {Message message = messageCreator.createMessage(session);if (logger.isDebugEnabled()) {logger.debug("Sending created message: " + message);}doSend(producer, message);// Check commit - avoid commit call within a JTA transaction.if (session.getTransacted() && isSessionLocallyTransacted(session)) {// Transacted session created by this template -> commit. JmsUtils.commitIfNecessary(session);}}finally {JmsUtils.closeMessageProducer(producer);}}?在發送消息還是遵循著消息發送的規則,比如根據Destination創建MessageProducer、創建Message,并使用MessageProducer實例來發送消息。
3.接收消息
?我們通常使用JmsTemplate.receive(destination)來接收簡單的消息,那么這個功能Spring是如何封裝的呢?
public Message receive(Destination destination) throws JmsException {return receiveSelected(destination, null);} public Message receiveSelected(final Destination destination, @Nullable final String messageSelector) throws JmsException {return execute(session -> doReceive(session, destination, messageSelector), true);} protected Message doReceive(Session session, Destination destination, @Nullable String messageSelector)throws JMSException {return doReceive(session, createConsumer(session, destination, messageSelector));} protected Message doReceive(Session session, MessageConsumer consumer) throws JMSException {try {// Use transaction timeout (if available).long timeout = getReceiveTimeout();ConnectionFactory connectionFactory = getConnectionFactory();JmsResourceHolder resourceHolder = null;if (connectionFactory != null) {resourceHolder = (JmsResourceHolder) TransactionSynchronizationManager.getResource(connectionFactory);}if (resourceHolder != null && resourceHolder.hasTimeout()) {timeout = Math.min(timeout, resourceHolder.getTimeToLiveInMillis());}Message message = receiveFromConsumer(consumer, timeout);if (session.getTransacted()) {// Commit necessary - but avoid commit call within a JTA transaction.if (isSessionLocallyTransacted(session)) {// Transacted session created by this template -> commit. JmsUtils.commitIfNecessary(session);}}else if (isClientAcknowledge(session)) {// Manually acknowledge message, if any.if (message != null) {message.acknowledge();}}return message;}finally {JmsUtils.closeMessageConsumer(consumer);}}實現的套路還是和發送差不多,同樣還是使用execute函數來封裝多余的操作,而最終的目的還是通過consumer.receive()來接收消息,其中的過程就是對于MessageConsumer的創建以及一些輔助操作。?
?參考:《Spring源碼深度解析》 郝佳 編著:?
轉載于:https://www.cnblogs.com/Joe-Go/p/10314334.html
總結
以上是生活随笔為你收集整理的Spring----JmsTemplate的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二进制流操作
- 下一篇: bootstrap-multiselec