相信后端的同学在平时开发时都大多都使用到spring boot来开发,那么在使用bean工厂注册bean时说不定会遇到过Bean named 'aaa' is expected to be of type 'bbb' but was actually of type 'bbb'这个报错,那么这个问题到底是怎么引起的呢?如何解决呢?且听我慢慢讲解。
有一天开发时突然收到上级发来的微信信息,他说他在我的项目中进行相关api测试时遇到了这样的问题叫我马上解决下,我发给大家看下。
一看到是上级发来的信息,于是马上停下了手头上的工作,开始迅速分析并解决问题了。有些同学可能纳闷,这个报错描述得跟标题中的并不一样呀,是不是跑题了?其实仔细分析下,你会发现上级发的这个报错信息其实就是造成Bean named ‘aaa‘ is expected to be of type ‘bbb‘ but was actually of type ‘bbb‘这个报错的根本原因!从字面上可以知道两个不同包路径下都有RiskKnowledgeBuilder这个类,这两个RiskKnowledgeBuilder类在bean工厂中注册的bean的名称都为riskKnowledgeBuilder,所以就互相发生了冲突,进而导致了bean工厂在按照名称(byName)来装配RiskKnowledgeBuilder类到其它类时发现这个类所对应的bean的名称虽然也是riskKnowledgeBuilder,但bean的类型却是已经注册好的名称也为riskKnowledgeBuilder但却是不同类型(处于不同包路径下)的RiskKnowledgeBuilder类的报错。下面我贴出这两个不同包路径下的RiskKnowledgeBuilder类的截图,大家可以可以比较下。
路径1:
路径2:
从上图我们不难看出这两个RiskKnowledgeBuilder类在bean工厂中注册的bean名称都为riskKnowledgeBuilder。既然找到原因并定位好问题所在,那么解决问题便不在话下了。那么怎么解决呢?其实很简单,两步搞定它
1、 第一步,既然注册的bean名称重复了,那么我们可以修改其中一个RiskKnowledgeBuilder类所注册的bean的名称修改为riskKnowledgeBuilder1,如下所示:
@Component("storageEyeInterface")
@Slf4j
public class EyeInterface {}
2.第二步,既然修改了该类注册的bean名称,那么我们在装配该类在其它类时,不能只单单使用@Autowired(按照类型来装配)和@Resource(按照名称来装配)这样的注解进行专配bean,因为这样的话spring都是默认将bean的名称设为的第一个字母小写这样的格式,比如上面的RiskKnowledgeBuilder如果用户不自己自定义的注册的bean名称的话,它在spring中默认的bean名称就是riskKnowledgeBuilder。所以我们可以两种方式进行改进:
第一种使用@Resource注解(按照名称来装配):
@Resource(name = "storageEyeInterface")
EyeInterface eyeInterface;
第二种使用@Autowired注解(使其也按照名称来装配)*:
@Autowired
@Qualifier("storageEyeInterface")
private EyeInterface eyeInterface;
按照上面的步骤我很快就把该问题修复了,是不是很简单?写这篇博客时我也参考了另外一篇博客,那篇博客写得简明扼要,也是不错的,大家对我的解释如果还有疑惑的可以看下下面这篇博客。
Spring boot注入组件Bean named ‘XXX’ is expected to be of type ‘TTT’ but was actually of type ‘TTT’
其实大多数人每次看到问题,不管三七二十一就来个疯狂的百度搜索、谷歌搜索的等等,只想先把问题解决再说,但这样虽然问题很快解决了,但你对问题的理解还不是很透彻。所以其实我们可以换个解决问题的思路。什么思路呢?很简单,也就是如下步骤:
- 分析产生这个问题的根本原因,找到导致这个报错出现的根源;
- 按照自己的理解多去尝试解决问题,多去试错;
- 自己多次尝试后依然解决不了,这时再去网上进行搜索或者寻求别人的帮助;
- 解决问题后找个时间进行思考总结,比如如何避免下次犯踩同样的坑,还有没有更好的方法等等。