如果我在RabbitTemplate上直接设置它们,为什么Spring需要在Converter和ClassMapper上使用@Bean?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果我在RabbitTemplate上直接设置它们,为什么Spring需要在Converter和ClassMapper上使用@Bean?相关的知识,希望对你有一定的参考价值。

我想了解为什么我需要用getMessageConverter标记classMapper@Bean方法,甚至直接在我的自定义RabbiteTemplate中设置它们。

没有@Bean并将它们传递给private,消息中没有正确包含TypeId

所以,使用@Bean和public方法,我在消息上有正确的标题:

headers: __TypeId__:    OrderProducer

没有它们,消息包含不正确的TypeId:

headers: __TypeId__:    com.projet.order.message.OrderProducer

没有classMapper的默认行为是什么。

看代码:

@Bean(name = "sendCommandOrderCreate")
public RabbitTemplate sendCommandOrderCreate() {
    RabbitTemplate rabbitTemplate = createRabbitTemplate(getMessageConverter());
    rabbitTemplate.setExchange("order.exchange");
    rabbitTemplate.setRoutingKey("order.cmd.create");
    return rabbitTemplate;
}

private RabbitTemplate createRabbitTemplate(final MessageConverter messageConverter) {
    final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMessageConverter(messageConverter);
    return rabbitTemplate;
}

@Bean
public Jackson2JsonMessageConverter getMessageConverter() {
    Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
    jackson2JsonMessageConverter.setClassMapper(classMapper());
    return jackson2JsonMessageConverter;
}

@Bean
public DefaultClassMapper classMapper() {
    DefaultClassMapper classMapper = new DefaultClassMapper();
    Map<String, Class<?>> idClassMapping = new HashMap<>();
    idClassMapping.put(OrderProducer.class.getSimpleName(), OrderProducer.class);
    idClassMapping.put(OrderConsumer.class.getSimpleName(), OrderConsumer.class);
    classMapper.setIdClassMapping(idClassMapping);
    return classMapper;
}

我是如何在服务中注入bean的:

public OrderService(@Qualifier("sendCommandOrderCreate") RabbitTemplate rabbitTemplate) {
    this.rabbitTemplate = rabbitTemplate;
}
答案

我发现了这个问题。我决定使用另一个Mapper:DefaultJackson2JavaTypeMapper

private DefaultJackson2JavaTypeMapper classMapper() {
    DefaultJackson2JavaTypeMapper classMapper = new DefaultJackson2JavaTypeMapper();
    Map<String, Class<?>> idClassMapping = new HashMap<>();
    idClassMapping.put(OrderProducer.class.getSimpleName(), OrderProducer.class);
    idClassMapping.put(OrderConsumer.class.getSimpleName(), OrderConsumer.class);
    classMapper.setIdClassMapping(idClassMapping);
    return classMapper;
}

调试代码并查找ClassMapper的不同实现后,我可以找到这个映射器。 DefaultClassMapper无法提供我期待的行为,我无法解释为什么用@Bean声明它可能会改变他的行为(可能是Spring上的一个bug)。

以上是关于如果我在RabbitTemplate上直接设置它们,为什么Spring需要在Converter和ClassMapper上使用@Bean?的主要内容,如果未能解决你的问题,请参考以下文章

消息模板-RabbitTemplate

Spring RabbitTemplate - 如何在发送时自动创建队列

如何在IIS上创建机器密钥?

RabbitTemplate 连接到 RabbitMQ:获取 - NOT_FOUND - 无队列

如何使用 RabbitTemplate 模仿 SimpMessagingTemplate.convertAndSendToUser?

Spring-AMQP 和直接回复