Spring在单值注入时如何按类型查找匹配的Bean,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
创新互联建站主营广德网站建设的网络公司,主营网站建设方案,App定制开发,广德h5微信小程序开发搭建,广德网站营销推广欢迎广德等地区企业咨询
我经常写如下代码:
@Autowired private AService aservice;
不知你是否也好奇,Spring是如何找到AService类型的Bean的呢?,我们就聊聊这个->单值注入时如何按类型查找匹配的Bean.
很简单,核心就3步。
Spring在DefaultListableBeanFactory.findAutowireCandidates方法中实现。 其部分源码如下:
String[] candidateNames = BeanFactoryUtils .beanNamesForTypeIncludingAncestors ( this, requiredType, true, descriptor.isEager());
这个beanNamesForTypeIncludingAncestors的作用就是,获取requiredType(AService)类型所有匹配的beanName(包含先祖BeanFactory)。
beanNamesForTypeIncludingAncestors内部是如果实现的呢?我概括了下简要逻辑如下:
遍历所有的BeanDefinition,获得所有的BeanName.
针对所有的BeanName,先尝试获取单例进行匹配,若未匹配上再以Bean Definition进行匹配。
匹配时,如果Bean是FactoryBean,先尝试FactoryBean生产的实际Bean进行匹配,若未匹配上再以FactoryBean 进行匹配。
DefaultListableBeanFactory.determinePrimaryCandidate实现了筛选首选Bean的逻辑, 其中的核心方法是isPrimary,该方法是判断当前Bean是否是首选Bean的。源码如下:
protected boolean isPrimary(String beanName, Object beanInstance) { if (containsBeanDefinition(beanName)) { return getMergedLocalBeanDefinition(beanName).isPrimary(); } BeanFactory parent = getParentBeanFactory(); return (parent instanceof DefaultListableBeanFactory && ((DefaultListableBeanFactory) parent).isPrimary(beanName,beanInstance)); }
getMergedLocalBeanDefinition(beanName).isPrimary()方法,对应AbstractBeanDefinition的primary属性,该属性被赋值的地方是在AnnotatedBeanDefinitionReader.doRegisterBean方法中。有如下逻辑。
//省略甚多代码...... for (Class qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } //省略很多代码....
看到这,我们可以得出一个结论:
被@Primary注解的bean,单值注入时会作为首选。
Spring是如何确定Bean的优先级的呢?
在DefaultListableBeanFactory.determineHighestPriorityCandidate中,实现按优先级选择Bean其中,获取Bean的优先级的逻辑在getPriority方法中,如下:
protected Integer getPriority(Object beanInstance) { Comparator