上一篇文章:《妈妈再也不用担心我的学习系列》之RabbitMQ快速入门
前言
在我们公司日常用RabbitMQ的时候如果多个服务都用到了队列,那么势必会有很多影响(如果不是广播模式队列是轮询接收消息的)所有这时候我们肯定是要去区别每一个服务的队列,方法会有很多种但是这里我推荐一下动态的修改队列方法
1. BeanPostProcessor简介
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
2. 实现BeanPostProcessor接口
public class QueueNameBeanPostProcessor implements BeanPostProcessor {
// 应用名称
@Value("${spring.application.name}")
private String appName;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 判断bean是否队列类型
if(bean instanceof Queue){
Queue queue=(Queue)bean;
String queueName=queue.getName(); // 队列名
boolean durable=queue.isDurable(); // 是否持久化
boolean exclusive=queue.isExclusive(); // 是否单独连接
boolean autoDelete=queue.isAutoDelete(); // 是否自动删除
boolean ignoreDeclarationExceptions = queue.isIgnoreDeclarationExceptions();
Map<String,Object> arguments=queue.getArguments();
String newQueueName=appName.concat(".").concat(queueName);
// 生成新的队列
queue=new Queue(newQueueName,durable,exclusive,autoDelete,arguments);
queue.setIgnoreDeclarationExceptions(ignoreDeclarationExceptions);
System.out.println(beanName + "-- old -->" + queueName + "-- new -->"+newQueueName);
return queue;
}
return bean;
}
}
3. 继承RabbitListenerAnnotationBeanPostProcessor类(这是队列监听初始类)
public class QueueNameListenerBeanPostProcessor extends RabbitListenerAnnotationBeanPostProcessor {
@Value("${spring.application.name}")
private String appName;
@Override
protected void processListener(MethodRabbitListenerEndpoint endpoint, RabbitListener rabbitListener, Object bean, Object adminTarget, String beanName) {
super.processListener(endpoint, rabbitListener, bean, adminTarget, beanName);
// 获取监听队列名称
Collection<String> queueNames = endpoint.getQueueNames();
// 修改监听队列名
queueNames = queueNames.stream().map(name -> appName.concat(".").concat(name)).collect(Collectors.toList());
endpoint.setQueueNames(queueNames.toArray(new String[queueNames.size()]));
System.out.println("listen queue-name newName - " + endpoint.getQueueNames());
}
}
4. 配置RabbitConfig
@Configuration
public class RabbitConfig {
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
}
/**
* 声明队列时设置应用名称为队列名前缀
*
* @return
*/
@Bean
public BeanPostProcessor queueNameHandler() {
return new QueueNameBeanPostProcessor();
}
/**
* 给所有RabbitListener队列名称添加应用名称前缀
*
* @return
*/
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public QueueNameListenerBeanPostProcessor queueNameListenerBeanPostProcessor() {
return new QueueNameListenerBeanPostProcessor();
}
/**
* 覆盖RabbitListenerAnnotationBeanPostProcessor后必须覆盖RabbitListenerEndpointRegistry
*
* @return
*/
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME)
public RabbitListenerEndpointRegistry defaultRabbitListenerEndpointRegistry() {
return new RabbitListenerEndpointRegistry();
}
}
5. 启动看看效果
可以看到我们已经成功修改了这样就不用担心多应用使用RabbitMQ了
监听的队列也自动加了前缀