这里介绍的源码主要是涉及springboot框架下的rabbitmq客户端代码(具体在springframework.amqp.rabbit包下,区分一下不由springboot直接接管的spring-rabbit的内容),springboot基于RabbitMQ的Java客户端建立了简便易用的框架。
springboot的框架下相对更多地使用消费者Consumer和监听器Listener的概念,这两个概念不注意区分容易混淆。默认情况下,springboot中消费者为单线程串行消费的模型,体现了队列的特性。
在springboot的框架下使用rabbitmq的一般步骤
- 启动rabbitmq服务器,springboot项目引入依赖
- 配置信息,有两种方式
- 配置文件配置
- 配置类配置SimpleMessageListenerContainer
- 实现消息处理类ChannelAwareMessageListener处理业务逻辑,或用@RabbitListener注解
这两种方式其实异曲同工,@RabbitListener的方式在实际使用时创建MessagingMessageListenerAdapter,这个对象是ChannelAwareMessageListener接口的实现类,实现了onMessage()方法,这个方法利用了适配器模式,能够调用注解标注的方法,而实现ChannelAwareMessageListener的方式比较直白就是实现onMessage()方法
源码解析
关于SimpleMessageListenerContainer
SimpleMessageListenerContainer是在spring项目中使用RabbitMQ关键的类,用来接收并处理消息的。阅读源码可以从这个类入手。
-
首先关注构造器,需要传入
ConnectionFactory用于获取连接,这跟原生rabbitmq是一致的,都从Connection连接开始。 -
关键属性
concurrentConsumers:指定要创建的并发消费者的数量。默认值为1。建议增加并发使用者的数量,以便扩展从队列传入的消息的消耗。但是,请注意,一旦注册了多个消费者,将无法保证顺序。一般来说,对于低容量队列,坚持使用1个消费者。同时不能超过maxConcurrentConsumers(如果设置了)。maxConcurrentConsumers:设置消费者数量的上限。默认为concurrentConsumers。消费者可以根据需求增加,但不会小于concurrentConsumers。acknowledgeMode:消息确认模式// 自动确认消息 container.setAcknowledgeMode(AcknowledgeMode.NONE); // 根据情况确认消息 container.setAcknowledgeMode(AcknowledgeMode.AUTO); // 手动确认消息 container.setAcknowledgeMode(AcknowledgeMode.MANUAL); -
绑定组件:
-
设置消费者的Consumer_tag和Arguments:container.setConsumerTagStrategy可以设置消费者的 Consumer_tag, container.setConsumerArguments可以设置消费者的 Arguments
container.setConsumerTagStrategy(queue -> "order_queue_"+(++count)); //设置消费者的Arguments Map<String, Object> args = new HashMap<>(); args.put("module","订单模块"); args.put("fun","发送消息"); container.setConsumerArguments(args);
spring的亮点在于用注解简化了很多代码操作,其中最常用的当属@RabbitListener
@RabbitListener(queues = {
BiMqConstant.BI_QUEUE_NAME}, ackMode = "MANUAL")
public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
}
从@RabbitListener入手
1、从spring开启RabbitMQ的注解模式,@EnableRabbit导入RabbitBootstrapConfiguration配置类。
2、这个配置类定义了RabbitListenerAnnotationBeanPostProcessor和RabbitListenerEndpointRegistry两个bean。前者用来扫描加了@RabbitListener 的类,通过反射找到带注解的类,再找到对应的方法,存为handlerMethods。后者在注册终端后用于构建ListenerContainer(继承了RabbitListener注解内的信息,包括监听的队列和注解所在的类和方法)。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(RabbitBootstrapConfiguration.class)
public @interface EnableRabbit {
}
3、RabbitListenerEndpointRegistry通过创建MethodRabbitListenerEndpoint对象和SimpleRabbitListenerContainerFactory工厂bean,生成SimpleMessageListenerContainer对象。
(RabbitListenerAnnotationBeanPostProcessor中拥有注解信息,如队列名,以及被标注注解的方法,所以endpoint的注册还是在processor类中)
(processor中有注册员成员变量registrar的registerEndpoint()注册endpoint,registrar有注册处registry成员变量注册利用registerListenerContainer()的createListenerContainer()注册container)
public class RabbitListenerEndpointRegistry implements SmartLifecycle{
private final Map<String, MessageListenerContainer> listenerContainers =
new ConcurrentHashMap<String, MessageListenerContainer>();
//注册终端
public void registerListenerContainer(RabbitListenerEndpoint endpoint, RabbitListenerContainerFactory<?> factory,
boolean startImmediately) {
String id = endpoint.getId();
synchronized (this.listenerContainers) {
//创建 listenerContainer
MessageListenerContainer container = createListenerContainer(endpoint, factory);
this.listenerContainers.put(id, container);
……
if (startImmediately) {
startIfNecessary(container);
}
}
}
protected MessageListenerContainer createListenerContainer(RabbitListenerEndpoint endpoint,
RabbitListenerContainerFactory<?> factory) {
//调用RabbitListener容器工厂的createListenerContainer方法获取RabbitListener容器
MessageListenerContainer listenerContainer = factory.createListenerContainer(endpoint);
return listenerContainer;
}
4、SimpleMessageListenerContainer对象保存了要监听的队列名(可以是configuration时set的也可以是@RabbitListener中标注的),创建了用于处理消息的MessagingMessageListenerAdapter实例(实际上是一个listener)
public class MethodRabbitListenerEndpoint extends AbstractRabbitListenerEndpoint {
......
@Override
protected MessagingMessageListenerAdapter

最低0.47元/天 解锁文章
607

被折叠的 条评论
为什么被折叠?



