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

导读:本篇文章讲解 spring-boot不同包结构下,同名类冲突导致服务启动失败解决方案,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

项目背景:

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

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,如果查不到则抛异常;如果查到,那即是它了
 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14136.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!