sspring 消息通常用的使用方法:
1.建立一个发送端
2.建立一个接收端,
3.测试,
1.通常会与Spring 的JMS使用。
2.如下使用Spring整合ActivateMQ:
参考使用方法:
https://www.iteye.com/blog/elim-1893676
3.Spring 在源码级别是如何整合activateMQ 的呢?
考虑2:(Spring整合JMS的使用)
Spring整合JMS的引用中定义三种类型的消息监听器,分别是MessageListener、SessionAwareMessageListener和MessageListenerAdapter。
三者之间区别是什么呢?
1.3.1 MessageListener
MessageListener是最原始的消息监听器,它是JMS规范中定义的一个接口。其中定义了一个用于处理接收到的消息的onMessage方法,该方法只接收一个Message参数。
1.3.2 SessionAwareMessageListener
SessionAwareMessageListener是Spring为我们提供的,它不是标准的JMS MessageListener。MessageListener的设计只是纯粹用来接收消息的,假如我们在使用MessageListener处理接收到的消息时我们需要发送一个消息通知对方我们已经收到这个消息了,那么这个时候我们就需要在代码里面去重新获取一个Connection或Session。SessionAwareMessageListener的设计就是为了方便我们在接收到消息后发送一个回复的消息,它同样为我们提供了一个处理接收到的消息的onMessage方法,但是这个方法可以同时接收两个参数,一个是表示当前接收到的消息Message,另一个就是可以用来发送消息的Session对象。
1.3.3 MessageListenerAdapter
MessageListenerAdapter类实现了MessageListener接口和SessionAwareMessageListener接口,它的主要作用是将接收到的消息进行类型转换,然后通过反射的形式把它交给一个普通的Java类进行处理。
MessageListenerAdapter会把接收到的消息做如下转换:
TextMessage转换为String对象;
BytesMessage转换为byte数组;
MapMessage转换为Map对象;
ObjectMessage转换为对应的Serializable对象。
(如果真正的目标处理器是一个MessageListener或者是一个SessionAwareMessageListener,那么Spring将直接使用接收到的Message对象作为参数调用它们的onMessage方法,而不会再利用反射去进行调用),那么我们在定义一个MessageListenerAdapter的时候就需要为它指定这样一个目标类。这个目标类我们可以通过MessageListenerAdapter的构造方法参数指定
问题1:但是如果指定的目标处理器是一个普通的Java类时Spring将利用Message进行了类型转换之后的对象作为参数通过反射去调用真正的目标处理器的处理方法,那么Spring是如何知道该调用哪个方法呢?
原因是:当我们没有指定该属性时,Spring会默认调用目标处理器的handleMessage方法。
问题2:当我们用于处理接收到的消息的方法的返回值不为空的时候,Spring会自动将它封装为一个JMS Message,然后自动进行回复。回复消息将发送到哪里呢?
第一,可以通过发送的Message的setJMSReplyTo方法指定该消息对应的回复消息的目的地。这里我们把我们的生产者发送消息的代码做一下修改,在发送消息之前先指定该消息对应的回复目的地为一个叫responseQueue的队列目的地,
第二,通过MessageListenerAdapter的defaultResponseDestination属性来指定。
问题3: 既然我们可以通过两种方式来指定MessageListenerAdapter自动发送回复消息的目的地,那么当我们两种方式都指定了而且它们的目的地还不一样的时候会怎么发送呢?
eg:当两种方式都指定了消息的回复目的地的时候使用发送消息的setJMSReplyTo方法指定的目的地将具有较高的优先级,MessageListenerAdapter将只往该方法指定的消息回复目的地发送回复消息。
参考博文:https://www.iteye.com/blog/elim-1893676
考虑3:spring 如何整合MQ:
在spring 中使用模板方法来代替消息发送。spring整合acivaiteMQ 要从JMSTempalte 分析。
JmsTemplate
在配置文件中我们定义了JmsTemplate,先来看看JmsTemplate的类层次结构:
虽然出现了常见的InitializingBean接口,但是该接口实际上只是一个验证的功能。
看实际的方法调用:
public void send(final Destination destination, final MessageCreator messageCreator) throws JmsException {
this.execute(new SessionCallback<Object>() {
public Object doInJms(Session session) throws JMSException {
JmsTemplate.this.doSend(session, destination, messageCreator);
return null;
}
}, false);
}
这种风格及其类似于JdbcTemplate类的实现风格,通过提取一个公共的方法作为最底层,最通用的功能实现,然后用回调函数的不同来区分个性化的功能。
下面先分析通用代码的抽取:抽取了Connection,Session的创建以及关闭的通用处理方式。
个性化的代码放在了回调函数doInJms中进行实现,实现的方式大概步骤是通过Destination创建MessageProceducer,创建Message,并使用MessageProcedure实例来发送消息。
接收消息的实现,套路与消息发送差不多。最终通过consumer.receive()实现 消息的接收。
监听器容器:
用于查看等待消息的到达的特殊的bean,一旦消息到达就可以获取到消息。
监听器容器
(1)SimpleMessageListenerContainer,不支持事务,只能处理固定数量的JMS会话
(2)DefaultMessageListenerContainer,建立在SimpleMessageListenerContainer之上,支持事务
初始化工作:
(1)属性的验证,connectionFactory和destination属性是否为空
(2)初始化,由于可以创建多个Session和MessageConsumer来接收消息(最好在Destination类型为Queue才使用多个MessageConsumer,否则消息的处理可能会因为并发的原因而出现错误;不应该在Destination为Topic时使用多个MessageConsumer,其原因也是因为并发),
问题如何监听多个消息呢?
创建多个多个Session和MessageConsumer来接收消息
Spring的处理方式是通过创建对应数量的线程,每个线程都作为独立的接收者循环接受消息,
线程实现类:
AsyncMessageListenerInvoker
流程如下:
1.允许无限制的接收消息,2.需要控制消息的数量,其实两者的最终逻辑都是通过invokeListener方法接收消息并激活监听器,只不过允许无限制接收消息的不同就在于允许暂停线程,以及恢复线程。Spring在处理这个问题上是通过使用全局控制变量lifecycleMonitor的wait方法来暂停线程,并且通过lifecycleMonitor的notifyAll方法恢复线程。
2.讨论消息接受的处理方式:
当讨论DefaultMessageListenerContainer时由于存在事务管理所以没法复用模板中的方法
其中包括了1.接收消息,2.模板方法,调用子类的实现,3.激活监听器,4.处理空消息
参考博文:
https://blog.youkuaiyun.com/weixin_40134367/article/details/79567044