@Autowired与@Resource源码区别
1、废话不多讲,直接干:
定位到
populateBean(beanName, mbd, instanceWrapper); 依赖注入的入口
2、主要看:PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//依赖注入过程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//老版本用这个完成依赖注入过程,@Autowired的支持
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
3、这个方法就是对postprocessor接口的运用,查看其实现类,这两个类就是处理类,一个处理Autowired,一个处理Resource
4、先看Autowired的吧
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); }
第一行是从收集好的注解信息中,拿到注解信息,其实就是需要依赖注入的信息,再看 下面的方法
element.inject(target, beanName, pvs);
我们只看属性的依赖注入,所以是选择第一个实现方法。
5、跟踪到这一段代码
try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); }
6、再跟踪到这里
if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); }
7、进去后里面有很多判断,@value的解析也在内,暂时不做分析,直接定位到这里
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; }
意思是找到候选者bean,findAutowireCandidates()方法中是根据type来找到所有的beanName,也就是根据类型查找
如果候选者是空,那么说明确实没有找到对应的依赖bean,注入值是空,如果注解上没有标注可以注入为空标记,则抛异常。
8、下面就比较有意思了
if (matchingBeans.size() > 1)
如果根据type找到不止一个bean,此时要另做判断,直接在代码后面做注释吧。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) { Class<?> requiredType = descriptor.getDependencyType(); String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);寻找一个有@Primary注解的实现类作为依赖注入的类 if (primaryCandidate != null) { return primaryCandidate; } String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);寻找一个有@Priority(2) 注解的实现类,并且取值最小的那一个。
if (priorityCandidate != null) {
return priorityCandidate;
} // Fallback 在下面没看懂,不做解释
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance))
|| matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
} return null;
}
如果以上都没判断出合格的bean则返回空。
9、最后else中是只有一个候选bean
else { // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); }
10、最后调用getBean操作
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
总结一下:根据类型查找候选者,如果候选者为空,则注入一个空;如果是多个,查找最合适的那一个,都不合适返回空;如果
刚刚是一个,则调用getBean,返回bean。区别的话,等下一篇介绍@Resource后,自然而然就明白了。