All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fqm.framework.mq.config.EmqxMqAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/*
 * @(#)EmqxMqAutoConfiguration.java
 * 
 * Copyright (c) 2015, All Rights Reserved
 * 项目名称 : fqm-spring-boot-starter-mq-emqx
 * 创建日期 : 2022年11月23日
 * 修改历史 : 
 *     1. [2022年11月23日]创建文件 by 傅泉明
 */
package com.fqm.framework.mq.config;

import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.fqm.framework.mq.MqFactory;
import com.fqm.framework.mq.MqMode;
import com.fqm.framework.mq.annotation.MqListenerAnnotationBeanPostProcessor;
import com.fqm.framework.mq.client.EmqxClient;
import com.fqm.framework.mq.exception.MqException;
import com.fqm.framework.mq.listener.EmqxMqListener;
import com.fqm.framework.mq.listener.MqListenerParam;
import com.fqm.framework.mq.template.EmqxMqTemplate;

/**
 * Emqx消息队列自动装配
 * MqProperties加载,并在MqAutoConfiguration后加载
 * SmartInitializingSingleton接口在Bean加载完成后,加载EmqxMq
 * @version 
 * @author 傅泉明
 */
@Configuration
@AutoConfigureAfter(MqAutoConfiguration.class)
@ConditionalOnBean(MqProperties.class)
public class EmqxMqAutoConfiguration implements SmartInitializingSingleton, ApplicationContextAware {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private ApplicationContext applicationContext;
    
    @Value("${server.port:}")
    private String port;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    } 

    @Bean
    @ConditionalOnMissingBean
    @ConfigurationProperties(prefix = "emqx")
    EmqxProperties emqxProperties() {
        return new EmqxProperties();
    }

    /**
     * 发送消息的客户端
     * @param properties
     * @return
     */
    @Bean(name = "emqxClient", initMethod = "connect", destroyMethod = "destroy")
    @ConditionalOnMissingBean
    EmqxClient emqxClient(EmqxProperties properties) {
        EmqxClient emqxClient = null;
        try {
            emqxClient = new EmqxClient(properties.getConnectString())
            .setCleanSession(properties.getCleanSession())
            .setConnectionTimeoutSecond(properties.getConnectionTimeoutSecond())
            .setKeepAliveIntervalSecond(properties.getKeepAliveIntervalSecond())
            .setPassword(properties.getPassword())
            .setUsername(properties.getUsername());
        } catch (MqttException e) {
            e.printStackTrace();
        }
        return emqxClient;
    }

    @Bean
    @ConditionalOnMissingBean
    @Order(300)
    EmqxMqTemplate emqxMqTemplate(MqFactory mqFactory, EmqxClient emqxClient) {
        EmqxMqTemplate emqxMqTemplate = new EmqxMqTemplate(emqxClient.getMqttClient());
        mqFactory.addMqTemplate(emqxMqTemplate);
        return emqxMqTemplate;
    }
    
    @Override
    public void afterSingletonsInstantiated() {
        MqListenerAnnotationBeanPostProcessor mq = applicationContext.getBean(MqListenerAnnotationBeanPostProcessor.class);
        MqProperties mp = applicationContext.getBean(MqProperties.class);
        EmqxProperties emqxProperties = applicationContext.getBean(EmqxProperties.class);
        // 注册 监听消息的客户端
        int i = 0;
        for (MqListenerParam v : mq.getListeners()) {
            String name = v.getName();
            MqConfigurationProperties properties = mp.getMqs().get(name);
            if (properties != null && MqMode.EMQX == properties.getBinder()) {
                String group = properties.getGroup();
                String topic = properties.getTopic();
                Assert.isTrue(StringUtils.hasText(topic), "Please specific [topic] under mq.mqs." + name + " configuration.");
                Assert.isTrue(StringUtils.hasText(group), "Please specific [group] under mq.mqs." + name + " configuration.");
                String beanName = "emqxListener." + i;
                // 动态注册
                //将applicationContext转换为ConfigurableApplicationContext
                ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
                // 获取bean工厂并转换为DefaultListableBeanFactory
                DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
                if (!applicationContext.containsBean(beanName)) {
                    
                    EmqxMqListener emqxMqListener = new EmqxMqListener(v.getMethod(), v.getBean(), null, topic, group);
                    
                    // 通过BeanDefinitionBuilder创建bean定义
                    BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                            .genericBeanDefinition(EmqxClient.class);
                    beanDefinitionBuilder.addConstructorArgValue(emqxProperties.getConnectString());
                    beanDefinitionBuilder.addConstructorArgValue(emqxMqListener);
                    beanDefinitionBuilder.addConstructorArgValue(topic);
                    // 应用程序的端口号
                    beanDefinitionBuilder.addConstructorArgValue(port);
                    beanDefinitionBuilder.setDestroyMethodName("destroy");
                    
                    beanDefinitionBuilder.addPropertyValue("cleanSession", emqxProperties.getCleanSession());
                    beanDefinitionBuilder.addPropertyValue("connectionTimeoutSecond", emqxProperties.getConnectionTimeoutSecond());
                    beanDefinitionBuilder.addPropertyValue("keepAliveIntervalSecond", emqxProperties.getKeepAliveIntervalSecond());
                    beanDefinitionBuilder.addPropertyValue("password", emqxProperties.getPassword());
                    beanDefinitionBuilder.addPropertyValue("username", emqxProperties.getUsername());
                    
                    // 注册bean
                    defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
                    // 实例化
                    EmqxClient client = (EmqxClient) applicationContext.getBean(beanName);
                    // 在 client 连接之前,初始化 EmqxMqListener 的 client
                    emqxMqListener.setClient(client.getMqttClient());
                    // 建立连接
                    try {
                        client.connect();
                    } catch (MqttException e) {
                        throw new MqException(e);
                    }
                    i++;
                    logger.info("Init EmqxMqListener,bean={},method={},topic={},group={}", v.getBean().getClass(), v.getMethod().getName(), topic, group);
                }
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy