Spring Cloud Stream报错:Invalid bean definition with name:bean definition with this name already exist

当想使用 Spring Cloud Stream 让微服务自己生产的消息自己消费时,如果使用的@Input("xxx")与@Output("xxx")注解中的"xxx"名称相同,启动程序将会报错:
Invalid bean definition with name 'xxx' defined in xxx: bean definition with this name already exists

完整错误记录及解决方法:

首先,为了生产和消费消息,需要定义一个输入通道、一个输出通道:

public interface StreamClient {
    String INPUT = "myMessage";
    String OUTPUT = "myMessage";

    @Input(StreamClient.INPUT)
    SubscribableChannel input();

    @Output(StreamClient.OUTPUT)
    MessageChannel output();
}

通过 INPUTOUTPUT 使用相同的名称,让生产消息和消费消息指向相同的Topic,从而实现消费自己发出的消息。
接下来,创建一个HTTP接口,并通过上面定义的输出通道触来生产消息:

@RestController
public class SendMessageController {
    @Autowired
    private StreamClient streamClient;

    @GetMapping("/sendMessage")
    public void process() {
        String message = "now " + new Date();
        streamClient.output().send(MessageBuilder.withPayload(message).build());
    }
}

已经有生产消息的实现,下面来创建对输入通道的监听,以实现消息的消费逻辑,需在该类名上标记 @EnableBinding(xxx.class) 注解:

@Component
@EnableBinding(StreamClient.class)
@Slf4j
public class StreamReceiver {

    @StreamListener(value = StreamClient.INPUT)
    public void process(String message) {
        log.info("StreamReceiver: {}", message);
    }
}

这看似天衣无缝的操作,如果你在这时启动,将会看到如下报错信息:

org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myMessage' defined in com.imooc.order.server.message.StreamClient: bean definition with this name already exists - Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.imooc.order.server.message.StreamClient; factoryMethodName=input; initMethodName=null; destroyMethodName=null
	at org.springframework.cloud.stream.binding.BindingBeanDefinitionRegistryUtils.registerBindingTargetBeanDefinition(BindingBeanDefinitionRegistryUtils.java:64) ~[spring-cloud-stream-2.0.1.RELEASE.jar:2.0.1.RELEASE]
以下省略...

解决方法:
根据错误提示:Invalid bean definition with name 'myMessage' defined in com.imooc.order.server.message.StreamClient: bean definition with this name already exists,没有启动成功的原因是:已经存在了一个名为myMessage的Bean,那么为什么会重复创建这个Bean呢?

当我们使用@Output@Input注解来定义消息通道时,都会根据传入的通道名称来创建一个Bean,而在上面的例子中,因为我们需要实现对自己生产的消息进行消费,所以我们需要定义的 @Output 和 @Input 名称相同的Topic,这样一来,便会生成相同Bean,以至报错bean definition with this name already exists

既然这样,我们定义相同的通道名是行不通了,那么我们只能通过定义不同的通道名,并为这两个通道配置相同的目标Topic来将这一对输入输出指向同一个实际的Topic。
对于上面的错误程序,只需要做如下两处改动:
第一步:修改通道名,使用不同的名字

public interface StreamClient {
    String INPUT = "myMessageTopicInput";
    String OUTPUT = "myMessageTopicOutput";
    
    @Input(StreamClient.INPUT)
    SubscribableChannel input();

    @Output(StreamClient.OUTPUT)
    MessageChannel output();
}

第二步:在配置文件中,为这两个通道设置相同的Topic名称

spring:
  cloud:
    stream:
      bindings:
        myMessageTopicInput:
          group: order
          destination: same-topic
          content-type: application/json
        myMessageTopicOutput:
          group: order
          destination: same-topic
          content-type: application/json

这样,这两个输入输出通道就会都指向名为same-topic的Topic了。
最后,再启动该程序,没有报错。然后访问controller:localhost:8080/sendMessage,可以在控制台中看到如下输出信息:

2020-03-17 22:09:56.490  INFO 84 --- [e-topic.order-1] c.i.order.server.message.StreamReceiver  : StreamReceiver: now Tue Mar 17 22:09:56 CST 2020

至此,已解决错误,希望能帮助到更多的伙伴们!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值