文章目录
- @Bean 断点跟不进去
- 为什么需要多个同类型bean
- 怎么友好处理同类型bean【任选一种】
- 彩蛋
@Bean 断点跟不进去
结论:你的其他代码 或者底层依赖,一定有改类型的自动注入代码
,在Spring 机制中,默认拒绝Bean重写,你一定遇到启动失败之后有这样的建议
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
对于这样的建议,强烈建议不要听取spring的建议,不要设置allow-bean-definition-overriding
这个配置否则很多问题都会导致bean的创建并没有按你期望的执行,而且在运行期间才暴露,在生产环境肯定会有一定影响。除了这个影响就是你以为自动注入成功了,实际上断点都过不去!!这种离奇事件都是因为放开导致的,如果不放开,spring才会自动帮你检查出来
不要跟我说指定Bean顺序就好了,这个放开就是后续所有的问题都因为被默认放开而难以排查,如果你的项目是个人维护还好,换一个人你就是坑主!
最可怕的是当很多人维护后都重写过相同bean定义,并且覆盖了bean也能满足需求,有些新手还不懂而庆幸解决了,而到其中一个人真正发现需要同时用多个bean定义时,必须要还原这个默认配置时, 各种报错 让他头皮发麻
那么到底是为什么会出现这个问题,因为Spring源码中所有的bean在创建前都是放在DefaultListableBeanFactory#beanDefinitionBeanMap属性中key是beanName,因此如果你的beanName相同,就会被检测出来【前提没有改上述配置】
为什么需要多个同类型bean
在实际复杂的业务场景,配置多个数据源包括不限制于【DB、ES、Kafka、MQ】都有可能是多套并行在某个业务中,这时候注入多个同类型bean是必不可免的
怎么友好处理同类型bean【任选一种】
一定要按name区分好你的多个同类bean作为前提
- 不要单纯使用@Autowire,要配合@Qualified,实时上官方都建议使用@Resource,默认基于byName查询
- 使用map注入,这也是ok的
@Resource private Map<String,DataSource> dataSourceMap;
# 这个好处是你可以按需取出你在某个场景需要的bean,非常方便
- Spring4.3 以后支持了ObjectProvider 这种方式在构造参数、方法参数根据自动注入使用也很方便,其带排序的迭代器相当不错,处理多个bean也是非常友好的
彩蛋
各位路过大佬平时怎么看源码中bean的创建呢?假如你找了半天都没找到Bean的定义该怎么办?例如接入dynamic-database时,默认注入了ShardingDatasource,单独靠链接or全局搜索根本找不到
没搜到是因为某个依赖需要下载源码,默认你都不知道在哪自然不知道该怎么下载,除非你这个依赖源码安装,这样肯定不是最好的
幸运的是有个通用法则:
例如我不知道ShardingDataSource在什么时候创建的,可以通过临时实现是一个BeanPostProcessor,注入到配置中,然后去拦截对应的bean父接口类型,打一个断点
这时候会在idea启动时跟踪到这,然后你只需要点击debug 面板 找到doCreateBean 的地方查看对应mbd属性 找到FactoryMethodMetaData ->declareClassName 即可知道Bean 的来源如下:
定位发现datasource的创建来源是org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration
点进去完美定位到目标Bean的创建过程
这个方法是万能的,笔者经常使用该方式解决疑难问题
授之以渔持续更新,敬请期待!!