当前位置:网站首页>@Autowired annotation --required a single bean, but 2 were found causes and solutions
@Autowired annotation --required a single bean, but 2 were found causes and solutions
2022-08-10 19:57:00 【qq_43479892】
优质资源分享
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统. |
Python量化交易实战 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
@Autowired注解是springOne of the core tool used to support the dependency injection,But we will meet more or lessrequired a single bean, but 2 were found(2可能是其他数字)的问题,Next, we from the Angle of the source to see why this problem,And what is the solution to the problem?
首先我们写一个demoReplicate our this problem.First of all, we have an abstract classAbstractAutowiredDemo,两个实现类AutowiredDemo1,AutowiredDemo2.然后我们在AutowiredDemoController中通过@Autowired依赖注入AbstractAutowiredDemo.
@RestController
public class AutowiredDemoController {
@Autowired
private AbstractAutowiredDemo abstractAutowiredDemo;
}
@Component
public abstract class AbstractAutowiredDemo {
public abstract String print();
}
@Component
public class AutowiredDemo2 extends AbstractAutowiredDemo {
@Override
public String print() {
return "AutowiredDemo2";
}
}
@Component
public class AutowiredDemo1 extends AbstractAutowiredDemo {
@Override
public String print() {
return "AutowiredDemo1";
}
}
At this time we start the project will appear the following error,找到了两个,And lists the find is in fact the two abstract class implementation class.
接下来,We look at from the perspective of source,springIs how to find the dependence and inject.
With the view [email protected] method,我们全局搜索Autowired,Find a calledAutowiredAnnotationBeanPostProcessor,根据命名AutowiredAnnotationXXXWe can probably know this class is used to deal with [email protected]的.
进入AutowiredAnnotationBeanPostProcessor,We can know from the annotation class - this class can handle [email protected],@ValueAnd if support [email protected],Here we only focus [email protected]就行了,Other will see later,And in no arguments constructor sets to support these type.
然后开始进入正题,We begin to see,spring是如何处理,How to find the dependence and inject,But why is our main task is the above mistakes,Such a purposeful look,Despite what other details,To relatively easy to.
Here can look at the source code is a skill,之前的ComponentScanAnnotationParser很简单,里面只有一个parse方法,We know it,但是在AutowiredAnnotationBeanPostProcessor这个里面,这么多方法,我们应该看什么呢?First of all we want is processing annotation method,Should be provided out of the way,So should be apubilic方法,(We at ordinary times when coding should be also the habit,To providepublicMethods should be put in front,protect,peivateThis to the back,Because the smaller scope universality is lower,Use the smaller the probability).But in front of a fewpublic方法都是在set属性值,所以排除掉,Then followed by two name is withbean定义有关的,一个是合并,One is the reset,Can temporarily away from,Then followed a decision which one to use the constructor of,It should be findbeanAnd then when instantiated with,Then there is a rear handle properties,而我们的@AutowiredIs the annotations on the property field,Here we see a step,看看方法的实现,有Injection of autowired dependencies字样,And according to the name check metadata,The process of the injection again,Guess is that this method.
Then emphatically to seeAutowiredAnnotationBeanPostProcessor.postProcessProperties这个方法.
首先第一行,The method name is injection of metadata in finding.
进入方法AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata,We can see this code is to judgecache中是否已经有了,And whether need to refresh(The refresh is type is empty or notclazz,Can point in view),不需要直接返回,Need to start lock(Lock and then conducted a check,双重校验,小知识点,To avoid in the process of lock,已经put进去),And then to build metadatabuildAutowiringMetadata
进入方法AutowiredAnnotationBeanPostProcessor.buildAutowiringMetadata,See the first judgment,Do you remember just began to speak,This class handles the annotation type,Here is in the judgment,我们的@AutowiredIs certainly in the,And then in the middle ado…while循环,The current class, and its parent class is annotated fields,方法放入elements中,最终返回一个InjectionMetadata对象,And set up itstargetClass为clazz,injectedElements为elements.Now we need to be equivalent to dependency injection metadata found.
Then start injection process,我们回到postProcessProperties方法,Check the injection method.
进入InjectionMetadata.inject方法,We found in the metadata is used here,我们不管checkedElements,至少我们的injectedElements肯定是有的,In the previous step to find the metadata,我们已经set进去了,Next, we will continue to go down.
As we continue to enterinject方法的时候,There's a phrase we found the comments on,this和getResourceToInjectAll need to override this method,So this method is not we need injection method of realize.
Click the down arrow on the left,We can find two implementation methods,根据命名,一个处理field的,一个处理method的,Obviously we need here is processingfield的.
进入AutowiredFieldElement.inject方法,We see him first to determine whether the cache,Our hypothesis is the first time in here,没有缓存(Cache is certainly before loading in),So we should goelse分支.
进入AutowiredFieldElement.inject.resolveFieldValue方法,我们可以看到,Beginning is doing some preparation,可以忽略,The last is cached in will look up to,我们也可以不看,重点就是try中的内容,解决依赖.
进入方法AutowireCapableBeanFactory.resolveDependency,We need to find its implementation method,Click the down arrow on the left,You can see two implementation methods,According to the same name,The red box is obviously used to deal withbean的.
进入DefaultListableBeanFactory.resolveDependency方法,大概扫一眼,The front is in the judgmentdescriptor.getDependencyType()This value is the type of the class,Apparently our own definition of class,Is not this type,So we directly to the lastelse,elseIn the first sentence is if you are lazy loading,Is not loaded before,So the real logic in here.(In fact, we is to find a solution to rely on,而springMethod named are see article knowledge meaning,So we could start with positioning directly to the following,Found wrong again,This is to look at the source code when a train of thought)
进入DefaultListableBeanFactory.doResolveDependency方法,Here is the real find rely on the core of the,接下来我们仔细分析一下.
Step1:通过descriptor.resolveShortcut(this)返回shortcut,We order into this method view annotations can be found,This is used to do some resolution in advance,一般是spring自用的,If we no special Settings,一般不会用到,所以这个shortcut应该为null,方法不会返回.
Step2:通过getAutowireCandidateResolver().getSuggestedValue(descriptor)返回value,Point method view into,According to the comments to see,This is a default value for a given depend on the advice of,Should deal with [email protected]所以这里value为null,方法不返回.
Step3:通过resolveMultipleBeans返回multipleBeans,You can see inside is in the judgment of our current search depend on the type of what conditions is in line with the(stream或者集合类型,所以这个叫multi),而我们当前的typeIs the abstract class we define,所以这里multipleBeans也为null,方法不返回.
Step4:通过findAutowireCandidates返回matchingBeans(Actually see the method name,就是处理Autowired注解,To find the candidate),Point method view into.
进入方法DefaultListableBeanFactory.findAutowireCandidates,First of all, the first line, we can see in finding candidates name.
进入方法BeanFactoryUtils.beanNamesForTypeIncludingAncestors,We can see here and call a method,通过type获取beanNames,Point into the annotation can see here will get the current types ofbean的名称(Excludes abstract class,No longer deep inside,Can point into the),包括子类,Actually see here should probably guess,We through the above abstract classAbstractAutowiredDemoGot a subclass of it,So error is a subclass insideAutowiredDemo1和AutowiredDemo2.Middle section could then find out more,But here we don't care,Now we return directly,此时String[]Should contain two elements.
回到方法DefaultListableBeanFactory.findAutowireCandidates,我们可以发现,result中至少有两个元素,下面的forAre inside to continueadd,We no longer see here,继续往外走.
回到方法DefaultListableBeanFactory.doResolveDependency,matchingBeansAt least two elements in the,Will enter the following aif,而在ifIn the first code is in deciding which candidate selectionbean,There is also a point we solve the problem of.
进入DefaultListableBeanFactory.determineAutowireCandidateWhether will find it to find the Settingsprimary,priority,Have no word cycle,See if already loaded or is currently,The ultimate goal is to determine a candidate as di,But we have this case,Apparently decided not to.
After returning to outside method,因为@Aurowired的required默认就是为true,So will enter theif,Returns a find is not the only exception.
总结
@AutowiredAnnotation fields find and dependent process can be summarized as:Find need field di,通过classType search can be injected class(包括子类),Decided to inject class,注入.
So to solve the problem of articles began to appear,有两个办法:
1.In the search to evade,Is specified when the injectedDemo1还是Demo2
2.In the class decided to inject around,通过注解@Primary或者@Priority
边栏推荐
- 【CNN】刷SOTA的trick
- 报错:runtime error: reference binding to null pointer of type ‘std::vector<int, std::allocator<int>>‘
- Tf铁蛋白颗粒包载顺铂/奥沙利铂/阿霉素/甲氨蝶呤MTX/紫杉醇PTX等药物
- UnitTest中的Path must be within the project 问题
- 烟雾、空气质量、温湿度…自己徒手做个环境检测设备
- 【SemiDrive源码分析】【MailBox核间通信】52 - DCF Notify 实现原理分析 及 代码实战
- 你不知道的浏览器页面渲染机制
- Random函数用法
- 不止跑路,拯救误操作rm -rf /*的小伙儿
- WCF and TCP message communication practice, c # 】 【 realize group chat function
猜你喜欢
laya打包发布apk
铁蛋白-AHLL纳米颗粒|人表皮生长因子-铁蛋白重链亚基纳米粒子(EGF-5Cys-FTH1)|铁蛋白颗粒包载氯霉素Chloramphenicol-Ferritin
[email protected] NPs纳米酶|碳纳米管负载铂颗粒纳米酶|白血病拮抗多肽修饰的FeOPtPEG复合纳米酶"/>
Pt/CeO2单原子纳米酶|[email protected] NPs纳米酶|碳纳米管负载铂颗粒纳米酶|白血病拮抗多肽修饰的FeOPtPEG复合纳米酶
《分布式微服务电商》专题(一)-项目简介
网络虚拟化
转铁蛋白(Tf)修饰去氢骆驼蓬碱磁纳米脂质体/香豆素-6脂质体/多柔比星脂质体
Redis 持久化机制
leetcode 84.柱状图中最大的矩形 单调栈应用
Introduction to 3 d games beginners essential 】 【 modeling knowledge
whois信息收集&企业备案信息
随机推荐
QoS服务质量六路由器拥塞管理
多功能纳米酶Ag/PANI|柔性衬底纳米ZnO酶|铑片纳米酶|Ag-Rh合金纳米颗粒纳米酶|铱钌合金/氧化铱仿生纳米酶
子域名收集&Google搜索引擎语法
[Teach you how to do mini-games] How to lay out the hands of Dou Dizhu?See what the UP master of the 250,000 fan game area has to say
FEMRL: A Framework for Large-Scale Privacy-Preserving Linkage of Patients’ Electronic Health Rec Paper Summary
servlet映射路径匹配解析
我们用48h,合作创造了一款Web游戏:Dice Crush,参加国际赛事
工业基础类—利用xBIM提取IFC几何数据
赎金信问题答记
不止跑路,拯救误操作rm -rf /*的小伙儿
leetcode 84.柱状图中最大的矩形 单调栈应用
redis 事件
30分钟使用百度EasyDL实现健康码/行程码智能识别
ARouter使用自定义注解处理器,自动生成跳转Activity的代码,避免手动填写和管理path
多线程与高并发(五)—— 源码解析 ReentrantLock
Win11连接投影仪没反应怎么解决?
Today's bug, click on the bug that the Windows dynamic wallpaper disappears in the win10 taskbar, and no solution has been found yet.
Site Architecture Detection & Chrome Plugin for Information Gathering
Win11如何清除最近打开过的文件记录?
QoS服务质量七交换机拥塞管理