@RabbitListener起作用的原理是什么


这篇文章主要讲解了“@RabbitListener起作用的原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“@RabbitListener起作用的原理是什么”吧!在spring中,定义rabbitMq的消费者可以相当方便,只需要在消息处理类或者类方法加上@RabbitListener注解,指定队列名称即可。如下代码:注意!!!如果@RabbitListener加在类上面,需要有一个默认的处理方法@RabbitHandler(isDefault=true),默认是false。不设置一个true,消费mq消息的时候会出现“Listener method ‘no match’ threw exception”异常。原因在RabbitListenerAnnotationBeanPostProcessor.processMultiMethodListeners方法,有兴趣的可以看下。可以看到代码相当的简单。但是!!!为什么加上这个注解,就能作为一个consumer接受mq的消息呢?为啥处理mq消息的方法,入参可以那么随意?有经验的程序员,可能会有这样的设想:1、单纯看这些listener的代码,只是定义了由spring管理的bean,要能监听rabbitMq的消息,肯定需要有另外一个类,这个类会扫描所有加了@RabbitListener的bean,进行加工。2、看这些listener的代码,可以发现处理mq消息的,都是具体的某个方法。那加工的过程,应该就是利用反射拿到对象、方法和@RabbitListener中的queue属性,然后建立一个绑定关系(对象+方法)——>(queue的consumer)。queue的consumer在接收到mq消息后,找到绑定的“对象+方法”,再通过反射的方式,调用真正的处理方法。3、mq消息的处理方法,可以那么随意,应该是queue的consumer在调用真正处理方法之前,需要根据处理方法的参数类型,做一次数据转换。接下来,就去看看源码,看一下设想是不是正确的~~1、谁来扫描@RabbitListener注解的bean在springBoot使用rabbit,一般是在@Configuration类上加上@EnableRabbit注解来开启rabbit功能。那我们就去看看@EnableRabbit注解的源码,看这个注解的作用可以看到,这个注解的作用,是导入RabbitBootstrapConfiguration配置类RabbitBootstrapConfiguration 配置类的作用,就是定义了RabbitListenerAnnotationBeanPostProcessor 和RabbitListenerEndpointRegistry 两个bean。看到RabbitListenerAnnotationBeanPostProcessor 这个类名,就可以猜到,该类的实例bean就是用来扫描加了@RabbitListener 的类,并做一些加工。(“RabbitListenerAnnotationBean”——针对添加了@RabbitListener注解的bean; “PostProcessor”——后置加工)2、怎么建立(对象+方法)——>(queue的consumer)的映射关系分析一下RabbitListenerAnnotationBeanPostProcessor类的源码这个类的代码比较长,只贴部分比较主要的部分,其他的,可以自己查看源码进行了解。RabbitListenerAnnotationBeanPostProcessor实现了BeanPostProcessor(bean初始化后的后置处理)、Ordered(后置处理的排序)、BeanFactoryAware(注入BeanFactory)、BeanClassLoaderAware(注入BeanClassLoader)、EnvironmentAware(注入spring环境)和SmartInitializingSingleton(单例bean初始化后的回调) 6个接口。我们需要关注的是BeanPostProcessor接口定义的方法,看postProcessAfterInitialization方法的代码,大致流程为:1、通过AopUtils得到bean代理的对象的class2、判断缓存中是否有该class的类型元数据,如果没有则调用buildMetadata方法生成类型元数据并放入缓存3、遍历加了@RabbitListener注解的方法,调用processAmqpListener方法进行处理4、调用processMultiMethodListeners方法对加了@RabbitHandler的方法进行处理关于buildMetadata方法:代码不复杂,就是利用反射,拿到class中,添加了@RabbitListener和@RabbitHandler注解的方法。另外,从代码中也可以看出,@RabbitHandler注解要生效,必须在class上增加@RabbitListener注解关于processAmqpListener方法:没有什么实际内容,就干两个事情:1、检查一下是否使用jdk代理,使用jdk代理方式必须实现了接口2、new一个MethodRabbitListenerEndpoint对象,交由processListener方法进行处理关于processListener方法:1、前面大半代码都是对MethodRabbitListenerEndpoint对象的属性设置:处理消息的bean、消息处理方法的工厂类、监听的队列名。。。。其中要关注一下setMessageHandlerMethodFactory方法,查看MessageHandlerMethodFactory接口的源码从入参和返回值可以看出来,这个工厂的作用就是将spring的bean对象和方法包装成一个InvocableHandlerMethod对象,也就是我们上面提到的(对象+方法)。2、通过beanFactory获取RabbitListenerContainerFactory类的bean。3、调用RabbitListenerEndpointRegistar的registerEndpoint方法注册mq消息消费端点。继续往下追,看一下RabbitListenerEndpointRegistar的代码:从上面的代码可以看出,我们关心的内容,应该是在RabbitListenerEndpointRegistry类的registerListenerContainer方法!!createListenerContainer方法调用了RabbitListenerContainerFactory接口的createListenerContainer方法创建一个MessageListenerContainer对象。在这里,如果是通过RabbitAutoConfiguration自动配置的,那么RabbitListenerContainerFactory接口的具体实现类是SimpleRabbitListenerContainerFactory,MessageListenerContainer接口的具体实现类是SimpleMessageListenerContainer。有兴趣的话,可以去看下rabbitMq自动配置的几个类。RabbitListenerContainerFactory接口的createListenerContainer方法是由AbstractRabbitListenerContainerFactory抽象类实现,代码如下:乍一看,都是对MessageListenerContainer实例的初始化,实际上有一行,相当重要“ endpoint.setupListenerContainer(instance); ”,这一行最终是走到用@RabbitLinstener注解的方法,使用的endpoint是MethodRabbitListenerEndpoint继承自AbstractRabbitListenerEndpoint,所以看看AbstractRabbitListenerEndpoint的createMessageListener方法从上面代码可以看出,createMessageListener方法返回了一个MessagingMessageListenerAdapter实例,MessagingMessageListenerAdapter实现了MessageListener接口到这里,我们就能得出一些结论:1、有@RabbitListener注解的方法,会生成MethodRabbitListenerEndpoint对象2、通过MethodRabbitListenerEndpoint对象和SimpleRabbitListenerContainerFactory工厂bean,生成SimpleMessageListenerContainer对象3、SimpleMessageListenerContainer对象保存了要监听的队列名,创建了用于处理消息的MessagingMessageListenerAdapter实例4、MessagingMessageListenerAdapter持有@RabbitListener注解的对象和方法,起到一个适配器的作用SimpleMessageListenerContainer是相当重要的一个类,,包装了整个mq消息消费需要的信息:1、保存了要监听的队列名,启动的时候,根据队列名创建从服务器拉取消息的consumer—免费云主机域名—BlockingQueueConsumer2、创建了一个MessagingMessageListenerAdapter对象,当consumer从服务器拿到消息后,由MessagingMessageListenerAdapter进行处理3、谁来做数据转换?是MessagingMessageListenerAdapter,有兴趣的,可以看看MessagingMessageListenerAdapter转换参数的源码。感谢各位的阅读,以上就是“@RabbitListener起作用的原理是什么”的内容了,经过本文的学习后,相信大家对@RabbitListener起作用的原理是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是百云主机,小编将为大家推送更多相关知识点的文章,欢迎关注!

相关推荐: C语言如何实现动态内存分配

今天小编给大家分享一下C语言如免费云主机域名何实现动态内存分配的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。C语言动态内存分配的详解1.为什么使…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 05/26 09:25
下一篇 05/26 09:25

相关推荐