SpringBoot消息源碼:JmsListener注解解析
JmsListener注解解析
JMS 消息分發(fā)送消息和接收消息兩種功能,發(fā)送消息很簡單,注入 Jms Template 到對應(yīng)的Bean 中即可使用。接收消息則需要使用@JmsListener 注解。
先看一下發(fā)送消息的官方示例。
@Component
public class MyBean {
private final JmsTemplate jmsTemplate;
@Autowired
public MyBean(JmsTemplate jmsTemplate) {
this. jmsTemplate = jmsTemplate;
}將 JmsTemplate 注入 MyBean 中,便可在該類的其他方法中使用 JmsTemplate 來發(fā)送消息了。
接收消息的官方代碼示例如下。
@Component
public class MyBean
@JmsListener(destination = " someQueue")
public void processMessage(String content) {
// ...
}
}當 JMS 的基礎(chǔ)構(gòu)件都完成初始化之后,可以使用@JmsListener 注釋任何 Bean 來創(chuàng)建偵聽器端點,就像上面的示例一樣。
@JmsListener 注解是由 Spring 提供的,它位于 spring-jms 包下。Spring 會對注解了@JmsListener 的 方 法 進 行 處 理 。在 這 一 過 程 中 主 要 使 用 到 同 一 包 下 的
JmsListenerAnnotation-BeanPostProcessor 類。該類中相關(guān)解析代碼如下。
@Override
public object postProcessAfterInitialization(0bject bean, String beanName )
throws
BeansException
if (bean instanceof AopInfrastructureBean| bean instanceof JmsListener-
ContainerFactory|I
bean instanceof JmsListenerEndpointRegistry) {
//忽略諸如作用域代理之類的 AOP 基礎(chǔ)結(jié)構(gòu)
return bean;
//通過工具類 AopProxyUtils 獲取最終的 Class 對象
Class> targetClass = AopProxyUtils . ultimateTargetClass(bean);//如果該目標 Class 不包含在 nonAnnotatedClasses(沒有被炷解的類)
//并且目標 Class 為基 FJmsListener 的候選類
if (!this . nonAnnotatedClasses . contains(targetClass) &&
AnnotationUtils. isCandidateClass(targetClass, JmsListener.class)) {
//獲取該類炷解有 Jmslistener 的方法集合
Map> annotatedMethods = MethodIntrospector.
selec tMethods(targetClass,
(MethodIntrospector . MetadataLookup>) met
hod -> {
Set listenerMethods = AnnotatedE lementUtil
getMergedRepeatableAnnotations (
method, JmsListener.class, JmsL isteners. class);
return ( !listenerMethods . isEmpty() ? listenerMethods : nu
11);
});
if (annotatedMethods . isEmpty()) {
//該類方法為空,則將該類放入 nonAnnotatedClasses 中
this . nonAnnotatedClasses . add(targetClass);
else
/如果方法集合不為空, 則遍歷方法集合并調(diào)用 processJmsL istener 方法進行后續(xù)
處理
annotatedMethods . forEach( (method, listeners)- >
listeners. forEach(listener -> processJmslisten
er(listener, method,
bean)));
return bean;
} 在上述代碼中,核心的處理流程就是通過 Bean 獲取最終符合條件的 Class 對象,然后獲取該 Class 對象中被@JmsListener 注解的方法集合,遍歷調(diào)用 processJmsListener 方法進行對應(yīng)的注冊操作。
在 processJmsListener 方 法中主要就是創(chuàng)建并初始化 MethodJmsListenerEndpoint 對象,同時創(chuàng)建了
JmsListenerContainerFactory 對象,然后通過 JmsListenerEndpointRegistrar的 registerEndpoint 方法將其進行注冊到 JmsListenerContainerFactory 中。
因此,在代碼中通過注解@JmsListener 便可進行消息的接收了。processJmsListener 部分代碼如下。
protected void processJmsListener(JmsListener jmsListener, Method mostScific-Method, object bean) {
Method invocableMethod = AopUtils . selectInvocableMethod (mostSpecificMetho
d, bean. getClass());
MethodImsListenerEndpoint endpoint = createMethodImslistenerEndpoint();
endpoint. setBean(bean);
// ... 省略大量 set 方法
//創(chuàng)建 JmsL istenerContainerFactory
JmsListenerContainerFactory> factory = null;
String containerFactoryBeanName = resolve ( jmsL istener. containerFactory
());
if (StringUtils . hasText(containerFactoryBeanName)) {
Assert. state (this. beanFactory != null, "BeanFactory must be set to obta
container factory by bean name") ;
try
factory = this. beanFactory . getBean(containerF actoryBeanN
ame, JmsL istener-
ContainerFactory.clas
s);
} catch (NoSuchBeanDefinitionException ex) {
//通過 JmsL istenerEndpointRegistrar 進行注冊
this . registrar. registerEndpoint(endpoint, factory);
}默認情況下,當使用了@JmsListener 注解,而又沒有自定義 JmsL istenerContainer-Factory時,Spring Boot 會自動創(chuàng)建一個默認的對象。
如果想創(chuàng)建多個
JmsListenerContainerFactory,可使用 Spring Boot 提供的DefaultJmsListenerContainerFactoryConfigurer 來創(chuàng)建,示例代碼如下。
@Configuration
static class JmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory myFactory(
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
configurer . configure(factory, connectionFactory());
factory. setMessageConverter (myMessageConverter());
return factory;}
}上 面 代 碼 定 義 完
JmsListenerContainerFactory 之 后 , 在 @JmsListener 注 解 中 指 定
containerFactory 為對應(yīng)的 Factory 名字(myFactory) 即可。
關(guān)于@JmsListener 的使用及原理,我們就講到這里。

小結(jié)
本章重點分析了 Spring Boot 中 JMS 和 ActiveMQ 的自動配置。ActiveMQ 很 好地實現(xiàn)了JMS 協(xié)議,同時又可以很方便地進行定制化實現(xiàn)。針對 JMS 的注解部分,Spring Boot 也提供了專門的自動配置類
JmsAnnotationDrivenConfiguration 進行一系列的默認配置 ,本章并未進行講解,讀者朋友可自行閱讀。而關(guān)于其他協(xié)議的自動配置實現(xiàn)基本相似,大家可進-步查看相關(guān)源代碼。
本文給大家講解的內(nèi)容是SpringBoot消息源碼解析:JmsListener注解解析
下篇文章給大家講解的是SpringBootCache源碼解析:Cache自動配置;
覺得文章不錯的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
感謝大家的支持!
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。
