当前位置:网站首页>@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
边栏推荐
- About npm/cnpm/npx/pnpm and yarn
- Public Key Retrieval is not allowed(不允许公钥检索)【解决办法】
- TDD、FDD是什么意思?
- 越折腾越好用的 3 款开源 APP
- 基于TCP的聊天系统
- 优雅退出在Golang中的实现
- 『牛客|每日一题』岛屿数量
- 铁蛋白-AHLL纳米颗粒|人表皮生长因子-铁蛋白重链亚基纳米粒子(EGF-5Cys-FTH1)|铁蛋白颗粒包载氯霉素Chloramphenicol-Ferritin
- [教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
- UnitTest中的Path must be within the project 问题
猜你喜欢
随机推荐
水溶性合金量子点纳米酶|CuMoS纳米酶|多孔硅基Pt(Au)纳米酶|[email protected]纳米模拟酶|PtCo合金纳米粒子
About npm/cnpm/npx/pnpm and yarn
LeetCode·27.移除元素·双指针
pytorch使用Dataloader加载自己的数据集train_X和train_Y
FEMRL: A Framework for Large-Scale Privacy-Preserving Linkage of Patients’ Electronic Health Rec论文总结
“2022零信任神兽方阵”启动调研,欢迎各单位填报信息
365天挑战LeetCode1000题——Day 053 求解方程 解析 模拟
keepalived:故障检测自动修复脚本
力扣18-四数之和——双指针法
【无标题】基于Huffman和LZ77的GZIP压缩
Introduction to 3 d games beginners essential 】 【 modeling knowledge
flask的配置文件
QoS服务质量七交换机拥塞管理
报错:runtime error: reference binding to null pointer of type ‘std::vector<int, std::allocator<int>>‘
服务器上行带宽和下行带宽指的是什么
FEMRL: A Framework for Large-Scale Privacy-Preserving Linkage of Patients’ Electronic Health Rec Paper Summary
转铁蛋白Tf功能化β-榄香烯-雷公藤红素/紫杉醇PLGA纳米粒/雷公藤甲素脂质体(化学试剂)
[教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
几行深度学习代码设计包含功能位点的候选免疫原、酶活性位点、蛋白结合蛋白、金属配位蛋白
子域名收集&Google搜索引擎语法