谷粒商城 RabbitTemplate报错循环依赖

1、RabbitMQ配置类

@Configuration
public class MyRabbitConfig {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    @PostConstruct
    public void initRabbitTemplate() {
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confirm:correlationData[" + correlationData + "]=>ack:[" + ack +  "]=>cause:[" + cause + "]");
            }
        });
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                Message message = returnedMessage.getMessage();
                int replyCode = returnedMessage.getReplyCode();
                String replyText = returnedMessage.getReplyText();
                String exchange = returnedMessage.getExchange();
                String routingKey = returnedMessage.getRoutingKey();
                System.out.println("Fail Message[" + message + "]=>replyCode[" + replyCode + "]" +
                        "=>replyText[" + replyText + "]=>exchange[" + exchange + "]=>routingKey[" + routingKey + "]");
            }
        });
    }
}

2、模块启动时报错循环依赖

img

3、根据报错原因,在 RabbitAutoConfiguration 类的 rabbitTemplate() 和 rabbitTemplateConfigurer() 处添加断点

img

4、循环依赖产生原因

4-1、通常情况下,Spring会根据Bean之间的依赖关系来初始化它们

4-2、初始化配置类 MyRabbitConfig 时,发现依赖于 RabbitTemplate

4-3、在自动配置类 RabbitAutoConfiguration 中初始化 RabbitTemplate 时,发现依赖于 RabbitTemplateConfigurer

@AutoConfiguration
@ConditionalOnClass({RabbitTemplate.class, Channel.class})
@EnableConfigurationProperties({RabbitProperties.class})
@Import({RabbitAnnotationDrivenConfiguration.class, RabbitStreamConfiguration.class})
public class RabbitAutoConfiguration {
    @Configuration(proxyBeanMethods = false)
    @Import({RabbitConnectionFactoryCreator.class})
    protected static class RabbitTemplateConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public RabbitTemplateConfigurer rabbitTemplateConfigurer(RabbitProperties properties, ObjectProvider<MessageConverter> messageConverter, ObjectProvider<RabbitRetryTemplateCustomizer> retryTemplateCustomizers) {
            RabbitTemplateConfigurer configurer = new RabbitTemplateConfigurer(properties);
            configurer.setMessageConverter((MessageConverter)messageConverter.getIfUnique());
            configurer.setRetryTemplateCustomizers((List)retryTemplateCustomizers.orderedStream()
                                                   .collect(Collectors.toList()));
            return configurer;
        }
        @Bean
        @ConditionalOnSingleCandidate(ConnectionFactory.class)
        @ConditionalOnMissingBean({RabbitOperations.class})
        public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
            RabbitTemplate template = new RabbitTemplate();
            configurer.configure(template, connectionFactory);
            return template;
        }
    }
}

4-4、在自动配置类 RabbitAutoConfiguration 中初始化 RabbitTemplateConfigurer 时,发现依赖于 MyRabbitConfig 的 MessageConverter,并导致循环依赖

5、三种解决方法

5-1、将自定义 MessageConverter 与 RabbitTemplate 放入两个不同的配置文件中

@Configuration
public class MyRabbitConfig {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @PostConstruct
    public void initRabbitTemplate() {
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confirm:correlationData[" + correlationData + "]=>ack:[" + ack +  "]=>cause:[" + cause + "]");
            }
        });
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                Message message = returnedMessage.getMessage();
                int replyCode = returnedMessage.getReplyCode();
                String replyText = returnedMessage.getReplyText();
                String exchange = returnedMessage.getExchange();
                String routingKey = returnedMessage.getRoutingKey();
                System.out.println("Fail Message[" + message + "]=>replyCode[" + replyCode + "]" +
                        "=>replyText[" + replyText + "]=>exchange[" + exchange + "]=>routingKey[" + routingKey + "]");
            }
        });
    }
}
@Configuration
public class MyMessageConverterConfig {
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

5-2、使用静态内部类

@Configuration
public class MyRabbitConfig {
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    @Component
    public static class rabbitTemplateConfiguration {
        @Autowired
        private RabbitTemplate rabbitTemplate;
        @PostConstruct
        public void initRabbitTemplate() {
            rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
                @Override
                public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                    System.out.println("confirm:correlationData[" + correlationData + "]=>ack:[" + ack +  "]=>cause:[" + cause + "]");
                }
            });
            rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
                @Override
                public void returnedMessage(ReturnedMessage returnedMessage) {
                    Message message = returnedMessage.getMessage();
                    int replyCode = returnedMessage.getReplyCode();
                    String replyText = returnedMessage.getReplyText();
                    String exchange = returnedMessage.getExchange();
                    String routingKey = returnedMessage.getRoutingKey();
                    System.out.println("Fail Message[" + message + "]=>replyCode[" + replyCode + "]" +
                            "=>replyText[" + replyText + "]=>exchange[" + exchange + "]=>routingKey[" + routingKey + "]");
                }
            });
        }
    }
}

5-3、自定义 RabbitTemplate

@Configuration
public class MyRabbitConfig {
    private RabbitTemplate rabbitTemplate;
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setMessageConverter(messageConverter());
        rabbitTemplate.setMandatory(true);
        initRabbitTemplate();
        return rabbitTemplate;
    }
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    public void initRabbitTemplate() {
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confirm:correlationData[" + correlationData + "]=>ack:[" + ack +  "]=>cause:[" + cause + "]");
            }
        });
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                Message message = returnedMessage.getMessage();
                int replyCode = returnedMessage.getReplyCode();
                String replyText = returnedMessage.getReplyText();
                String exchange = returnedMessage.getExchange();
                String routingKey = returnedMessage.getRoutingKey();
                System.out.println("Fail Message[" + message + "]=>replyCode[" + replyCode + "]" +
                        "=>replyText[" + replyText + "]=>exchange[" + exchange + "]=>routingKey[" + routingKey + "]");
            }
        });
    }
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值