【实战】Spring生成beanName冲突的解决之道:附源码分析
一、问题描述
最近公司项目打算模块化,其实一个原因也是为了能够整合公司多个业务的代码,比如一个资源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冲突的解决之道:附源码分析相关推荐
- python程序员专用壁纸_程序员炫技必备:用Python生成马赛克画!(文末附源码)...
原标题:程序员炫技必备:用Python生成马赛克画!(文末附源码) 源 | Python与数据分析文 | 强哥 大家知道马赛克画是什么吗?不是动作片里的马赛克哦~~ 马赛克画是一张由小图拼成的大图,本 ...
- 【.NET Core项目实战-统一认证平台】第八章 授权篇-IdentityServer4源码分析
上篇文章我介绍了如何在网关上实现客户端自定义限流功能,基本完成了关于网关的一些自定义扩展需求,后面几篇将介绍基于IdentityServer4(后面简称Ids4)的认证相关知识,在具体介绍ids4实现 ...
- 04【Verilog实战】SPI协议底层硬件接口设计(附源码RTL/TB)
脚 本:makefile 工 具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序提供下载,[下载地址] 发现 ...
- Netty4.x: Server端 设置 option 警告 Unknown channel option ‘xxxx‘ for channel 分析及解决 (附源码分析)
一.问题背景: 最近某springboot项目想嵌入一个用户聊天功能,打算使用 Rabbitmq + Netty4.x + Redis 来开发高性能聊天功能.花费三天时间所有功能都已实现.启动时却警告 ...
- Netty实战:Springboot+Netty+protobuf开发高性能服务器 (附源码下载)
Springboot-cli 开发脚手架系列 Netty系列:Springboot使用Netty集成protobuf开发高性能服务器 文章目录 Springboot-cli 开发脚手架系列 简介 1. ...
- Spring学习总结(29)——Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)
在开发过程中,我们会遇到很多使用线程池的业务场景,例如异步短信通知.异步记录操作日志.大多数使用线程池的场景,就是会将一些可以进行异步操作的业务放在线程池中去完成.例如在生成订单的时候给用户发送短信, ...
- 厉害了!Spring Boot + Vue 开发移动端商城(附源码、文档、视频)!
Java大联盟 致力于最高效的Java学习 关注 B 站搜索:楠哥教你学Java 获取更多优质视频教程 前言 最近有不少小伙伴留言希望楠哥出一套 Spring Boot + Vue 项目实战教程, ...
- Spring Boot整合JWT实现用户认证(附源码)
点击上方"程序IT圈",选择"置顶公众号" 每天早上8点50分进来看看,就是最大的支持 来源:https://dwz.cn/yv1Do6e3 什么是JWT JW ...
- 富文本生成word并在线预览(附源码)
记录富文本内容生成word并在线预览碰到的问题,以及最终的解决方案. 一.需求 当前项目需要将页面富文本中的内容,生成word并在线预览. 二.解决方案1(未解决) 1. openoffice wor ...
最新文章
- 除了 AI,这些技术为 IIoT 插上飞向“4.0”的翅膀
- ​北京大学吴华君组诚聘医学/生信助理研究员和博士后
- 第四周实践项目7 多项式求和
- jquery选择器和基本操作
- stm32滴答计时器_stm32中的系统滴答定时器使用
- r语言 rgl 强制过程中_一个R语言中操纵矢量空间数据的标准化工具—sf
- 力扣--91. 解码方法
- HDFS/zookeeper/hbase初始化
- python表示数字6_Python3 数字Number(六)
- 《转》 在C++中使用TinyXML2解析xml
- clickhouse CollapsingMergeTree表引擎
- 深入Managed DirectX9(十五)
- Qt如何给一个button,悬浮 、按下设置不同的背景图
- 相册制作软件--4月精选婚纱相册模板{H1.爱的天空}样片
- Snipaste下载以及一部分使用的快捷方式
- pytorch 机器翻译 seq2seq 模型和注意力机制
- relativePath
- 小米手机TCP连接一些奇怪现象
- 4G工业路由器如何助力自动售货机更智能?
- redit高可用持久