• spring-boot不同包结构下,同名类冲突导致服务启动失败解决方案


    项目背景:

      两个项目的包结构和类名都很多相同,于是开始考虑使用加一级包进行隔离,类似于这种结构

    但是在启动的过程中,抛出来这样的异常:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'nameConflict' for bean class [xom.liuyun.beannameconflict.modelB.NameConflict] conflicts with existing, non-compatible bean definition of same name and class [xom.liuyun.beannameconflict.modelA.NameConflict]

    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:286) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:284) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:241) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]

    ... 13 common frames omitted。

    原因:

      spring提供两种beanName生成策略,基于注解的sprong-boot默认使用的是AnnotationBeanNameGenerator,它生成beanName的策略就是,取当前类名(不是全限定类名)作为beanName。由此,如果出现不同包结构下同样的类名称,肯定会出现冲突。

    解决方案如下:

      1. 自己写一个类实现 org.springframework.beans.factory.support.BeanNameGeneraot接口

    public class UniqueNameGenerator extends AnnotationBeanNameGenerator {
    
    
    
        @Override
    
        public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    
            //全限定类名
    
            String beanName = definition.getBeanClassName();
    
            return beanName;
    
        }
    
    }

     2. 在启动类上加注解@ComponentScan(nameGenerator = UniqueNameGenerator.class)使刚才我们自定义的BeanName生成策略生效。 

    @SpringBootApplication
    
    @ComponentScan(nameGenerator = UniqueNameGenerator.class)
    
    public class BeanNameConflictApplication {
    
    
    
        public static void main(String[] args) {
    
            SpringApplication.run(BeanNameConflictApplication.class, args);
    
        }
    
    }

    这样,问题就可以解决了。

    另外解决方式:

    解决办法,一:将其中一个实现类改为不同的名字;

                    二:将其中一个注解变更为一个name为非roleServiceImpl的注解@service(name="aaaa")。

    别名

    • @Autowired注解时,属性名即为默认的Bean名,如下面的logPrint就是获取beanName=logPrint的bean
    • @Resource(name=xxx) 直接指定Bean的name,来唯一选择匹配的bean

    说明:

    @Primary注解

    这个注解就是为了解决当有多个bean满足注入条件时,有这个注解的实例被选中

     @Resource 指定beanName的是否会被@Primary影响
    前面的@Autowired注解 + 属性名的方式,是按照第一节的方式选择呢,还是选择被@Primary标识的实例
    @Autowired + 随意的一个非beanName的属性,验证是否会选中@Primary标识的注解

    根据前面的执行,因此可以知晓,选择bean的方式如下

    存在@Primary注解时

    @Resource注解指定name时,根据name来查找对应的bean
    @Autowired注解,全部都用@Primary标识的注解
    @Primary注解要求唯一(非广义的唯一性,并不是指只能用一个@Primary,具体看前面)
    不存在@Primary注解时

    @Resource注解指定name时,根据name来查找对应的bean
    @Autowired注解时,根据属性名去查对应的Bean,如果查不到则抛异常;如果查到,那即是它了
     

    正因为当初对未来做了太多的憧憬,所以对现在的自己尤其失望。生命中曾经有过的所有灿烂,终究都需要用寂寞来偿还。
  • 相关阅读:
    MOCK服务小结
    微信收款「商业版」与「个人版」有什么区别?看完这篇你就懂!
    LB 负载均衡的层次结构
    中兴应用之星携手天翼开放平台:让APP开发更简单
    常见面试题之二叉树
    【深入JAVA EE】Spring配置文件解析
    spring-struts-mybatis整合错误集锦
    Redis安装
    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本号
    Android UI开发神兵利器之Icon
  • 原文地址:https://www.cnblogs.com/candlia/p/11919993.html
Copyright © 2020-2023  润新知