美文网首页
【源码阅读】看Spring Boot如何自动装配ActiveMQ

【源码阅读】看Spring Boot如何自动装配ActiveMQ

作者: 船前几度寄芳心 | 来源:发表于2018-07-05 16:12 被阅读0次

    源于好奇,我研究了一下Spring Boot中ActiveMQ相关组件是如何自动装配的。记录如下。

    源码路径

    本文以Spring Boot 1.5.10.RELEASE版本为例。

    在spring-boot-autoconfigure-1.5.10.RELEASE.jar中的spring.factories文件中可以找到相JMS自动装配类。

    org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
    org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
    

    在spring-jms-4.3.14.RELEASE.jar中包含了jms组件的所有具体功能类。

    Configuration类加载顺序

    顺序 类名 import引入
    1 JndiConnectionFactoryAutoConfiguration
    2 ActiveMQAutoConfiguration ActiveMQXAConnectionFactoryConfiguration, ActiveMQConnectionFactoryConfiguration
    3 JmsAutoConfiguration JmsAnnotationDrivenConfiguration, JmsBootstrapConfiguration(由JmsAnnotationDrivenConfiguration中的@EnableJms注解引入)

    以上罗列出了与ActiveMQ相关的配置类,默认ActiveMQ是采用JMS协议连接的。Spring的JMS消息组件接收与发送是毫不相关的体系。下文分别阐述。

    关键类列表

    类名 类别 作用
    JmsProperties Properties注入 spring.jms开头的配置项注入
    ActiveMQProperties Properties注入 spring.activmeq开头的配置项注入
    ActiveMQAutoConfiguration @Configuration 无具体代码,通过注解引入ActiveMQXAConnectionFactoryConfiguration与ActiveMQConnectionFactoryConfiguration两个配置类
    ActiveMQXAConnectionFactoryConfiguration @Configuration 配置ActiveMQ XA(点击这里了解XA)连接工厂
    ActiveMQConnectionFactoryConfiguration @Configuration 配置ActiveMQ连接工厂
    JmsAutoConfiguration @Configuration 与发送消息组件相关,初始化JmsTemplate与JmsMessagingTemplate(Spring4.1后引入)
    JmsAnnotationDrivenConfiguration @Configuration 与接收消息组件相关,初始化JmsListenerContainerFactory
    JmsBootstrapConfiguration @Configuration 初始化JmsListenerAnnotationBeanPostProcessor 与JmsListenerEndpointRegistry两个类的Bean
    JmsListenerAnnotationBeanPostProcessor Bean 自定义JmsListenerEndpointRegistrar行为,并将带有@JmsListener的方法注册到指定的JmsListenerContainerFactory中。
    JmsListenerEndpointRegistrar Bean 将JmsListenerEndpoint对象注册到JmsListenerEndpointRegistry对象中。

    发送消息

    发送消息组件的装配相对简单,主要代码都在ActiveMQConnectionFactoryConfigurationJmsAutoConfiguration两个类中。

    ActiveMQConnectionFactoryConfiguration

    class ActiveMQConnectionFactoryConfiguration {
    
        @Bean
        @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true)
        public ActiveMQConnectionFactory jmsConnectionFactory(ActiveMQProperties properties,
                ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
            ...
        }
    
        @Bean(destroyMethod = "stop")
        @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false)
        @ConfigurationProperties(prefix = "spring.activemq.pool.configuration")
        public PooledConnectionFactory pooledJmsConnectionFactory(
                    ActiveMQProperties properties,
                    ObjectProvider<List<ActiveMQConnectionFactoryCustomizer>> factoryCustomizers) {
                ...
        }
    
    }
    

    可以看到,此类根据配置项的不同初始化了ActiveMQ的连接工厂ActiveMQConnectionFactory或PooledConnectionFactory。

    JmsAutoConfiguration

    public class JmsAutoConfiguration {
    
        @Configuration
        protected static class JmsTemplateConfiguration {
            ...
            @Bean
            @ConditionalOnMissingBean
            @ConditionalOnSingleCandidate(ConnectionFactory.class)
            public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
                ...
            }
        }
    
        @Configuration
        @ConditionalOnClass(JmsMessagingTemplate.class)
        @Import(JmsTemplateConfiguration.class)
        protected static class MessagingTemplateConfiguration {
    
            @Bean
            @ConditionalOnMissingBean
            @ConditionalOnSingleCandidate(JmsTemplate.class)
            public JmsMessagingTemplate jmsMessagingTemplate(JmsTemplate jmsTemplate) {
                return new JmsMessagingTemplate(jmsTemplate);
            }
        }
    }
    

    从源码中可以看到,JmsAutoConfiguration主要作用是当JmsTemplateJmsMessagingTemplate两个类的对象不存在(没有由用户定义)时,初始化这两个类的默认Bean。

    至此JMS消息发送关键组件初始化完成。用户可以通过Spring获得JmsTemplateJmsMessagingTemplate对象发送消息。

    接收消息

    Spring Boot接收消息的方法有好几种(具体请参阅),最简单与常用的方式就是使用@JmsListener注解在方法上。

    Spring为每个带有@JmsListener注解的方法在后台构建了一个对应的MessageListenerContainer实例(老版本的Spring需要手动配置DefaultMessageListenerContainer,这里不再赘述)。

    为了能自动创建MessageListenerContainer,Spring提供了@EnableJms注解,通过JmsListenerAnnotationBeanPostProcessorBeanPostProcessor机制,指定带有@JmsListener注解的方法为一个MethodJmsListenerEndpoint,并将其通过JmsListenerEndpointRegistrar辅助类注册到JmsListenerEndpointRegistry中。此过程中,需要一个JmsListenerContainerFactory对象(由用户自定义创建或由Spring自动创建DefaultJmsListenerContainerFactory)来参与完成构建动作。几个关键类的关系图大致如下。

    JmsListener注册关键类结构图

    另外,用户也可以通过实现JmsListenerConfigurer来指定JmsListenerEndpointRegistrar对象在注册过程中的行为。

    下面看一下几个核心类的代码。

    JmsListenerAnnotationBeanPostProcessor

    public class JmsListenerAnnotationBeanPostProcessor
            implements MergedBeanDefinitionPostProcessor, Ordered, BeanFactoryAware, SmartInitializingSingleton {
    ...
            public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
            ....
                    for (Map.Entry<Method, Set<JmsListener>> entry : annotatedMethods.entrySet()) {
                        Method method = entry.getKey();
                        for (JmsListener listener : entry.getValue()) {
                            processJmsListener(listener, method, bean);
                        }
                    }
            ...
            }
    
            protected void processJmsListener(JmsListener jmsListener, Method mostSpecificMethod, Object bean) {
            ...
                    this.registrar.registerEndpoint(endpoint, factory);
            }
    

    从以上的源码片段可以看出,JmsListenerAnnotationBeanPostProcessor的主要作用是将带有@JmsListener的方法(Endpoint)注册到JmsListenerContainerFactory中。

    JmsAnnotationDrivenConfiguration

    class JmsAnnotationDrivenConfiguration {
    ...
        @Bean
        @ConditionalOnMissingBean
        public DefaultJmsListenerContainerFactoryConfigurer jmsListenerContainerFactoryConfigurer() {
            ...
        }
    
        @Bean
        @ConditionalOnMissingBean(name = "jmsListenerContainerFactory")
        public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
                DefaultJmsListenerContainerFactoryConfigurer configurer,
                ConnectionFactory connectionFactory) {
            ...
        }
    ...
    }
    

    从源码可以看出,JmsAnnotationDrivenConfiguration主要作用是当名称为“jmsListenerContainerFactory”的bean不存在时初始化一个DefaultJmsListenerContainerFactory。

    至此,接收消息的组件装配过程分析已完成。加上对应的配置项,用户可以从ActiveMQ中收到消息。

    相关文章

      网友评论

          本文标题:【源码阅读】看Spring Boot如何自动装配ActiveMQ

          本文链接:https://www.haomeiwen.com/subject/lzmeuftx.html