Spring通過代碼注冊Bean

業(yè)務背景

我所在公司系統(tǒng)要升級到jdk8, 其中一個工程需要從IBM MQ 切換到ActiveMQ。 消息發(fā)送方的消息隊列名稱是配置在數(shù)據(jù)庫中的,不同的環(huán)境有不同的配置,且同一個消息可能有不同的消息隊列名稱(因為是很古老的項目,所以誰也說不清楚為什么有這么多不同的隊列),但是為了在升級過程中不會讓客戶修改任何數(shù)據(jù),我們決定從程序入手解決不同對列名稱問題。我們的消息消費端是基于SpringBoot的工程。

思路

雖然消息生產方在數(shù)據(jù)庫中配置了多個消息隊列,但是我們的消費邏輯是一樣的。所以,我們就要用同一個消息消費者去消費這些隊列中的消息,消息消費流程如下圖。如何注冊達到這樣的效果呢?


activemq.png

注冊bean

我們使用spring常用的注冊bean的方式要么是通過xml文件配置,在啟動過程中加載解析,最終成為容器中的bean, 或者我們使用注解的方式,例如@Controller,@Service, @Resource,@Component,@Bean 等,上面是我們常用的方式。現(xiàn)在我們要通過java代碼的方式去生成bean.

  1. new一個對象,放到容器中
    程序初始化完成后,獲取上下文,直接把實例添加到容器中,然后給這個實例起一個名字。
AnnotationConfigServletWebServerApplicationContext beanFactory = (AnnotationConfigServletWebServerApplicationContext)context;
        RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
        beanDefinition.setAttribute("name","張老三");

        beanFactory.registerBeanDefinition("person",beanDefinition);
  1. 繼承 BeanDefinitionRegistryPostProcessor

@Configuration
public class DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor  {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {


        registerListener("1,2,3,4,5,6,7,8,9",new CustomerListener(),beanDefinitionRegistry);
       /* this.registerListener("test1",new RSSQLInvoiceUploadAgent(),beanDefinitionRegistry);
        this.registerListener("test2",new GPRetrievePaymentAgent(),beanDefinitionRegistry);
        this.registerListener("test3",new GPCustomerAgent(),beanDefinitionRegistry);*/
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    private void registerListener(String destination, MessageListener queueListener,BeanDefinitionRegistry beanDefinitionRegistry){
        if (StringUtils.isEmpty(destination)){
            return;
        }
        String[] jmsQueues = destination.split(",");



        String[] beans = beanDefinitionRegistry.getBeanDefinitionNames();
        for(int m=0;m<beans.length;m++){
            System.out.println(beans[m]);
        }

        for(int i=0;i<jmsQueues.length;i++){
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultMessageListenerContainer.class);
            beanDefinitionBuilder.addPropertyValue("cacheLevel",Integer.valueOf("1"));
            beanDefinitionBuilder.addPropertyValue("concurrentConsumers",Integer.valueOf("1"));
            beanDefinitionBuilder.addPropertyValue("connectionFactory",beanDefinitionRegistry.getBeanDefinition("cachingConnectionFactoryConfig"));
            beanDefinitionBuilder.addPropertyValue("messageListener",queueListener);
            beanDefinitionBuilder.addPropertyValue("destinationName",jmsQueues[i]);
            beanDefinitionBuilder.addPropertyValue("receiveTimeout",Long.valueOf("3000"));
            beanDefinitionRegistry.registerBeanDefinition(queueListener.getClass().getSimpleName()+i,beanDefinitionBuilder.getBeanDefinition());
        }
    }

但是最終沒有使用這種方法在我們實際的開發(fā)過程中,因為@JmsListener 是支持通過"," 分隔監(jiān)聽我們需要的消息隊列的。

demo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容