springboot-启动bean冲突的解决

 更新时间:2022年03月24日 11:31:08   作者:鬼~离未罔两  
这篇文章主要介绍了springboot-启动bean冲突的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

启动bean冲突

在一次启动中遇到了bean冲突的问题,提示存在两个名称重复的bean

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.test.api.Application]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'healthCheckController' for bean class [com.test.datahub.controller.HealthCheckController] conflicts with existing, non-compatible bean definition of same name and class [com.test.api.controller.HealthCheckController]

项目中包括多个模块,其中A、B两个模块都有同一个类:

HealthCheckController,检查更改信息发现,不知道谁在A模块添加了B模块的依赖,造成了这一问题,删除后解决

        <dependency>
            <groupId>com.test</groupId>
            <artifactId>B</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>

启动提示bean重复问题

先说结论

只需要在@FeignClient注解的contextId属性上加上独一的标示,即可解决问题

原理

是因为注册feignClient的时候会注册ClientConfiguration,参考代码如下

public void registerFeignClients(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   //...此处省略部分代码
   //
   for (String basePackage : basePackages) {
      Set<BeanDefinition> candidateComponents = scanner
            .findCandidateComponents(basePackage);
      for (BeanDefinition candidateComponent : candidateComponents) {
         if (candidateComponent instanceof AnnotatedBeanDefinition) {
            // verify annotated class is an interface
            //...省略部分代码
 
            //这块是把注解上的所有属性封装到map上
            Map<String, Object> attributes = annotationMetadata
            .getAnnotationAttributes(
            FeignClient.class.getCanonicalName());
 
            //这两个重点方法请看下面代码块
 
            //获取该feignClient的名字(重点关注该方法)
            String name = getClientName(attributes);
 
            //此方法就是spring注入beanDefination的步骤(重点关注该方法)
            registerClientConfiguration(registry, name,
                  attributes.get("configuration"));
 
            registerFeignClient(registry, annotationMetadata, attributes);
         }
      }
   }
}

上面的两处重点方法, 请看此处

//@param client 这个map就是通过上面的注解属性转map得到的
private String getClientName(Map<String, Object> client) {
   if (client == null) {
      return null;
   }
   //如果从contextId获取到名字,那么value有值的
   String value = (String) client.get("contextId");
   //如果value有值,那么如下3个if条件都不会走,所以contextId唯一就可以做到bean不重复,
   //如果value没有值,就会取value,因为多个client的serverName都是一样的,那么就会出现重复bean
   if (!StringUtils.hasText(value)) {
      value = (String) client.get("value");
   }
   if (!StringUtils.hasText(value)) {
      value = (String) client.get("name");
   }
   if (!StringUtils.hasText(value)) {
      value = (String) client.get("serviceId");
   }
   if (StringUtils.hasText(value)) {
      return value;
   }
 
   throw new IllegalStateException("Either 'name' or 'value' must be provided in @"
         + FeignClient.class.getSimpleName());
}
 
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
      Object configuration) {
   BeanDefinitionBuilder builder = BeanDefinitionBuilder
         .genericBeanDefinition(FeignClientSpecification.class);
   builder.addConstructorArgValue(name);
   builder.addConstructorArgValue(configuration);
   //在这个位置,创建beanDefinition,但是他创建的名字格式可以看出,唯一改变变量就是name,这个name就是上面看到的那个方法获取的
   registry.registerBeanDefinition(
         name + "." + FeignClientSpecification.class.getSimpleName(),
         builder.getBeanDefinition());
}

以上就是feign导致的springBean重复问题的解释,仅上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java处理日期时间的方法汇总

    Java处理日期时间的方法汇总

    这篇文章主要给大家介绍了利用Java中的Calendar 类处理日期时间的方法汇总,其中包括取日期的每部分、取当月的第一天或最后一天、求两个日期之间相隔的天数以及一年前的日期等等的示例代码,有需要的朋友们可以直接参考借鉴,下面来一起看看吧。
    2016-12-12
  • Mybatis分页插件PageHelper的分页原理剖析

    Mybatis分页插件PageHelper的分页原理剖析

    这篇文章主要介绍了Mybatis分页插件PageHelper的分页原理剖析,PageHelper作为一个启动器,那么就和其他启动器加载一样,先读取spring.factories文件里面配置的类,转成Bean加载本系统中,然后执行他的前置后置处理方法,完成初始化,需要的朋友可以参考下
    2023-08-08
  • 聊一聊SpringBoot服务监控机制

    聊一聊SpringBoot服务监控机制

    这篇文章主要介绍了聊一聊SpringBoot服务监控机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • SpringBoot整合Ip2region获取IP地址和定位的详细过程

    SpringBoot整合Ip2region获取IP地址和定位的详细过程

    ip2region v2.0 - 是一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现 ,这篇文章主要介绍了SpringBoot整合Ip2region获取IP地址和定位,需要的朋友可以参考下
    2023-06-06
  • java高并发之线程的基本操作详解

    java高并发之线程的基本操作详解

    本文主要介绍java高并发线程的基本操作,这里整理详细的资料来解释线程的知识,有需要的学习高并发的朋友可以参考下
    2021-10-10
  • SSH框架网上商城项目第8战之查询和删除商品类别功能实现

    SSH框架网上商城项目第8战之查询和删除商品类别功能实现

    SSH框架网上商城项目第8战之查询和删除商品类别功能实现,为项目增加功能,添加、更新、删除和查询操作,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • SpringBoot请求转发的方式小结

    SpringBoot请求转发的方式小结

    本文主要介绍了SpringBoot请求转发的方式,一共有两大类,一种是controller控制器转发一种是使用HttpServletRequest进行转发,本文就详细的介绍一下,感兴趣的可以了解一下
    2023-09-09
  • Java多线程Thread基础学习

    Java多线程Thread基础学习

    每一个正在执行的程序都是一个进程,资源只有一块,所以在同一时间段会有多个程序同时执行,但是在一个时间点上,只能由一个程序执行,多线程是在一个进程的基础之上的进一步划分,需要的朋友可以参考下
    2023-04-04
  • Java编程枚举类实战代码分享

    Java编程枚举类实战代码分享

    这篇文章主要介绍了Java编程枚举类实战代码分享,具有一定借鉴价值,需要的朋友可以了解下。
    2017-11-11
  • Java如何自动生成api文档

    Java如何自动生成api文档

    在 Java 开发中,自动生成 API 文档是一项非常实用的功能,这篇为大家介绍了几种常见的 Java 自动生成 API 文档的方式,需要的可以参考一下
    2025-02-02

最新评论