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

问题描述 投票:0回答:1

我想了解为什么我需要用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;
}
java spring rabbitmq spring-rabbit
1个回答
0
投票

我发现了这个问题。我决定使用另一个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)。

© www.soinside.com 2019 - 2024. All rights reserved.