我们知道无论是mybatis-plus、rocketmq等第三方优秀的框架都继承了springboot。那么如果我们想自己写一个简单的功能集成到springboot当中需要怎么做到呢?
接下来我们分下下rocketmq集成springboot的代码:
@RocketMQMessageListener是我们实现业务代码的监听实现类,通常它长这个样子:
@Slf4j
@Component
@RocketMQMessageListener(topic = TopicConst.REFERENCE_CODE_CREATE_SEND_EMAIL_SMS_TOPIC, consumerGroup = "txn_create_send_email_sms_consumer")
public class ReferenceCodeCreateNotifyConsumer implements RocketMQListener {
//业务代码
}
我们的一个linstener要想集成到rocketmq还需要很多的参数,这些参数统一的包装在了DefaultRocketMQListenerContainer实现类当中,并且DefaultRocketMQListenerContainer里面包含了一个DefaultMQPushConsumer实例。有了DefaultMQPushConsumer实例,我们就可以启动它实现一个rocketmq consumer端服务实例。
具体地:
1、rocketmq实现了RocketMQAutoConfiguration
注解实现了以下4个主要步骤。
1.1、@EnableConfigurationProperties(RocketMQProperties.class)
感知我们配置文件当中有关rocketmq的配置信息
1.2、@ConditionalOnClass({MQAdmin.class})
通过MQAdmin.class感知rocketmq-client包是否在类路径当中。
1.3、@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class,
引入RocketMQMessageConverter实例
引入ListenerContainerConfiguration实例
引入ExtProducerResetConfiguration实例
引入ExtConsumerResetConfiguration实例
引入RocketMQTransactionConfiguration实例
引入RocketMQListenerConfiguration实例
1.4、@AutoConfigureAfter({MessageConverterConfiguration.class})
注册RocketMQMessageListenerBeanPostProcessor 为RootBeanDefinition
类型实例。
RocketMQAutoConfiguration内部实现了以下两个步骤。
1、如果配置参数里面有name-server和producer.group,则注册DefaultMQProducer实例
2、如果配置参数里面有name-server、pull-consumer.group和pull-consumer.topic
,则注册DefaultLitePullConsumer实例。
再来看RocketMQMessageListenerBeanPostProcessor,其实现了BeanPostProcessor
接口,每一个类初始化之前和之后都会走到这个类的postProcessBeforeInitialization
和postProcessAfterInitialization方法当中。
Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class> targetClass = AopUtils.getTargetClass(bean);
RocketMQMessageListener ann = targetClass.getAnnotation(RocketMQMessageListener.class);
if (ann != null) {
RocketMQMessageListener enhance = enhance(targetClass, ann);
if (listenerContainerConfiguration != null) {
listenerContainerConfiguration.registerContainer(beanName, bean, enhance);
}
}
return bean;
}
当我们实现业务代码的监听类走到该方法的时候,会被感知到,并注册响应的container到spring上下文。
container的初始化肯定是会涉及到rocektmq启动需要的一大堆参数,这个不表,我们看下其初始化最重要的三件事儿
1、获取我们监听配置的topic、tag、group
2、获取配置文件中配置的参数,命名空间、nameserver等
3、最重要的是DefaultRocketMQListenerContainer实现了InitializingBean。当DefaultRocketMQListenerContainer初始化完毕之后会执行afterPropertiesSet方法。该方法里面包含了初始化consumer代码。
注意consumer里面的参数一部分是在DefaultRocketMQListenerContainer当中写死了,一部分则来自RocketMQMessageListener当中的配置,也就是说我们可以通过注解RocketMQMessageListener动态设定一些参数。
this.consumeMode = anno.consumeMode();
this.consumeThreadMax = anno.consumeThreadNumber();
this.consumeThreadNumber = anno.consumeThreadNumber();
this.messageModel = anno.messageModel();
this.selectorType = anno.selectorType();
this.selectorExpression = anno.selectorExpression();
this.consumeTimeout = anno.consumeTimeout();
this.maxReconsumeTimes = anno.maxReconsumeTimes();
this.replyTimeout = anno.replyTimeout();
this.tlsEnable = anno.tlsEnable();
this.namespace = anno.namespace();
this.delayLevelWhenNextConsume = anno.delayLevelWhenNextConsume();
this.suspendCurrentQueueTimeMillis = anno.suspendCurrentQueueTimeMillis();
this.awaitTerminationMillisWhenShutdown = Math.max(0, anno.awaitTerminationMillisWhenShutdown());
this.instanceName = anno.instanceName();
以上参数都可以通过监听配置参数调整。
consumer实例有了接下来就是如何启动.返回到container注册方法,当它初始化完DefaultRocketMQListenerContainer之后随机就启动了container,container启动随即就启动了consumer.这样回到图一,思路就清晰了。springboot整合rocketmq,每一个监听配置一个DefaultRocketMQListenerContainer,每一个DefaultRocketMQListenerContainer包含一个consumer,通过springboot的autoconfig方式将每一个RocketMQMessageListener实现类包装成一个DefaultRocketMQListenerContainer,最终由DefaultRocketMQListenerContainer来桥接我们的监听和consumer去实现功能。