一、问题描述

最近公司项目打算模块化,其实一个原因也是为了能够整合公司多个业务的代码,比如一个资源xxx,两个业务中都有对这个资源的管理,虽然是一个资源,但是是完全不同的定义、完全不同的表、不同的处理逻辑。所以打算把类名弄成一样的,但是包名不一样。

但这样会产生问题,按照Spring的默认beanName生成规则,会直接将类名首字母小写作为bean的名字,如两个模块里的这个资源都叫xxxJob,这样在Spring启动的时候就会报错。错误如下conflicts with existing, non-compatible bean definition of same name and class [xxxxJob],意思就是说两个bean同名了,这样启动就报错了。

二、源码分析

解决方法我们可以手动修改bean名称的生成策略,这里直接就是用实现类的全限定名称(com.abc.job.xxxJob)作为bean的名称。

翻翻源码,我们先来看默认生成规则:

1.判断bean上的注解中是否指定了名字,如果指定直接返回,否则去构造bean的名称。

public class AnnotationBeanNameGenerator implements BeanNameGenerator {@Overridepublic String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {if (definition instanceof AnnotatedBeanDefinition) {//看bean上的注解中是否指定了bean的名字String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);if (StringUtils.hasText(beanName)) {// 如果指定了名字,直接返回return beanName;}}// 没有指定名字,去构造一个bean的名称return buildDefaultBeanName(definition, registry);}。。。
}

2.bean构造逻辑

    protected String buildDefaultBeanName(BeanDefinition definition) {String beanClassName = definition.getBeanClassName();Assert.state(beanClassName != null, "No bean class name set");String shortClassName = ClassUtils.getShortName(beanClassName);return Introspector.decapitalize(shortClassName);}

这里definition.getBeanClassName()是获取全限定名称的,ClassUtils.getShortName是获取类名的,下面的Introspector.decapitalize实际上就是把首字母变小写的。

    public static String getShortName(String className) {Assert.hasLength(className, "Class name must not be empty");int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR);if (nameEndIndex == -1) {nameEndIndex = className.length();}String shortName = className.substring(lastDotIndex + 1, nameEndIndex);shortName = shortName.replace(INNER_CLASS_SEPARATOR, PACKAGE_SEPARATOR);return shortName;}

核心是getShortName方法,其实就是个字符串截取,将包和后缀都去掉,生成一个短bean的名称。

三、解决方案

到这里我们应该看得很清楚了,不同包名但相同类名的类,Spring的默认生成beanName规则生成出来的名称是一样的,难怪Spring在启动会报错了,那我们要做的就是修改beanName的生成规则,做法如下:

我们这里要设置为全限定名称,我们可以新写一个类,假设叫MyBeanNameGenerator

,然后继承AnnotationBeanNameGenerator之后重写buildDefaultBeanName方法,返回definition.getBeanClassName(),这样我们这个生成策略就写好了。代码如下:

public class BeanNameGenerator extends AnnotationBeanNameGenerator{@Overridepublic String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {//这里也也可以加自己的逻辑,比如只有特定包下面的bean需要使用这种生成规则,其他包下面的bean还采用默认生成规则,各位看官自己去发挥即可return  definition.getBeanClassName();}

接下来对@ComponentScan注解添加一个nameGenerator属性就好了,指定为我们自定义的bean生成策略。

@ComponentScan(basePackages = "com.xxx.job.**",nameGenerator = MyBeanNameGenerator.class)

这样就完美了,这时候所有bean的默认名称就是我们设置的全限定名了,不过如果我们在类上显式的写了bean的id的话,还是会用我们自定义的bean的name的。

最后:感谢我司可少大力支持!

【实战】Spring生成beanName冲突的解决之道:附源码分析相关推荐

  1. python程序员专用壁纸_程序员炫技必备:用Python生成马赛克画!(文末附源码)...

    原标题:程序员炫技必备:用Python生成马赛克画!(文末附源码) 源 | Python与数据分析文 | 强哥 大家知道马赛克画是什么吗?不是动作片里的马赛克哦~~ 马赛克画是一张由小图拼成的大图,本 ...

  2. 【.NET Core项目实战-统一认证平台】第八章 授权篇-IdentityServer4源码分析

    上篇文章我介绍了如何在网关上实现客户端自定义限流功能,基本完成了关于网关的一些自定义扩展需求,后面几篇将介绍基于IdentityServer4(后面简称Ids4)的认证相关知识,在具体介绍ids4实现 ...

  3. 04【Verilog实战】SPI协议底层硬件接口设计(附源码RTL/TB)

    脚  本:makefile 工  具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序提供下载,[下载地址] 发现 ...

  4. Netty4.x: Server端 设置 option 警告 Unknown channel option ‘xxxx‘ for channel 分析及解决 (附源码分析)

    一.问题背景: 最近某springboot项目想嵌入一个用户聊天功能,打算使用 Rabbitmq + Netty4.x + Redis 来开发高性能聊天功能.花费三天时间所有功能都已实现.启动时却警告 ...

  5. Netty实战:Springboot+Netty+protobuf开发高性能服务器 (附源码下载)

    Springboot-cli 开发脚手架系列 Netty系列:Springboot使用Netty集成protobuf开发高性能服务器 文章目录 Springboot-cli 开发脚手架系列 简介 1. ...

  6. Spring学习总结(29)——Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)

    在开发过程中,我们会遇到很多使用线程池的业务场景,例如异步短信通知.异步记录操作日志.大多数使用线程池的场景,就是会将一些可以进行异步操作的业务放在线程池中去完成.例如在生成订单的时候给用户发送短信, ...

  7. 厉害了!Spring Boot + Vue 开发移动端商城(附源码、文档、视频)!

      Java大联盟 致力于最高效的Java学习 关注 B 站搜索:楠哥教你学Java 获取更多优质视频教程 前言 最近有不少小伙伴留言希望楠哥出一套 Spring Boot + Vue 项目实战教程, ...

  8. Spring Boot整合JWT实现用户认证(附源码)

    点击上方"程序IT圈",选择"置顶公众号" 每天早上8点50分进来看看,就是最大的支持 来源:https://dwz.cn/yv1Do6e3 什么是JWT JW ...

  9. 富文本生成word并在线预览(附源码)

    记录富文本内容生成word并在线预览碰到的问题,以及最终的解决方案. 一.需求 当前项目需要将页面富文本中的内容,生成word并在线预览. 二.解决方案1(未解决) 1. openoffice wor ...

最新文章

  1. 除了 AI,这些技术为 IIoT 插上飞向“4.0”的翅膀
  2. ​北京大学吴华君组诚聘医学/生信助理研究员和博士后
  3. 第四周实践项目7 多项式求和
  4. jquery选择器和基本操作
  5. stm32滴答计时器_stm32中的系统滴答定时器使用
  6. r语言 rgl 强制过程中_一个R语言中操纵矢量空间数据的标准化工具—sf
  7. 力扣--91. 解码方法
  8. HDFS/zookeeper/hbase初始化
  9. python表示数字6_Python3 数字Number(六)
  10. 《转》 在C++中使用TinyXML2解析xml
  11. clickhouse CollapsingMergeTree表引擎
  12. 深入Managed DirectX9(十五)
  13. Qt如何给一个button,悬浮 、按下设置不同的背景图
  14. 相册制作软件--4月精选婚纱相册模板{H1.爱的天空}样片
  15. Snipaste下载以及一部分使用的快捷方式
  16. pytorch 机器翻译 seq2seq 模型和注意力机制
  17. relativePath
  18. 小米手机TCP连接一些奇怪现象
  19. 4G工业路由器如何助力自动售货机更智能?
  20. redit高可用持久

热门文章

  1. 中间件——构筑复杂分布式应用的关键技术(转)
  2. LeetCode-MySQL196. 删除重复的电子邮箱
  3. Elasticsearch了解多少,说说你们公司es的集群架构,索引数据大小,分片有多少,以及一些调优手段 。
  4. HTTP/2 in GO(一)
  5. React 第十二章 React思想
  6. ES6函数相关包含箭头函数
  7. CSS分别设置Input样式(按input类型
  8. 最近一段时间遇到的费了时间的问题
  9. java类型转换_Java类型转换
  10. 用Kubernetes搭建Etcd集群和WebUI