属性注入(populateBean)
处理 @Autowired 和 @Resource 标记的属性和方法(这里的方法不包括构造方法,因为构造方法在前面已经完成了推断)
问题:@Autowired 是 byType?,再 byName?
流程:
- 根据需要注入的类型找到所有的 beanName
- 遍历 beanName,找到需要注入的类型,并放入一个集合中(待推断)
- 如果待注入集合中只有一个符合条件的 class,则表示找到了要注入的 bean
- 如果带注入集合中有多个符合条件的 class,则继续按名称推断
- 看看有没有标记为 @Primary 注解的 bean,有则返回
- 判断有没有 @Priority 注解的 bean,有的话,返回值低的优先级作为 bean 返回
- 看看是不是有别名 bean 符合,有的话作为 bean 返回
- 如果都不满足,则抛出异常 NoUniqueBeanDefinitionException
- 根据 beanName 从单例池中获取所需要注入的 bean
- 利用反射完成属性注入
调用后置处理器
这里的后置处理器必须是 InstantiationAwareBeanPostProcessor 类型
for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// ★★★ 关键代码:进行属性填充// CommonAnnotationBeanPostProcessor 完成对 @Resource 属性的注入// AutowiredAnnotationBeanPostProcessor 完成对 @Autowired 属性的注入PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}
查找类的注入元数据(包括属性,方法)
根据当前要进行属性填充的 bean,找到当前 bean 需要注入的元数据(属性和方法)
// ★★★ 获取需要注入的元数据// 1、查找标记有 @Autowired 的 field// 2、查找标记有 @Autowired 的 methodInjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
根据类型查找
matchingBeans 很关键,先根据类型查找,看存在多少相同类型的 bean
- beanName:当前需要进行属性注入的 bean
- type:当前注入的属性的类型
- descriptor:当前注入的属性的包装,包括字段名称,类型,是不是方法等信息
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
根据名称查找
// ★★★ 如果找到多个符合条件的 bean// matchingBeans.size() > 1:则说明通过类型查找找到了多个符合条件的 beanif (matchingBeans.size() > 1) {// ★★★ 关键代码:开始根据名称进行推断,根据 descriptor 提供的 fieldName 来推断 autowiredBeanName// 由此可以推断,@Autowired 是先根据类型查找,如果找到多个,再根据名称查找// 此处根据需要注入的属性的名字推断,查找真正需要注入的 beanautowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {// In case of an optional Collection/Map, silently ignore a non-unique case:// possibly it was meant to be an empty collection of multiple regular beans// (before 4.3 in particular when we didn't even look for collection beans).return null;}}// ★ 从多个匹配的对象中根据 autowiredBeanName 获取 beaninstanceCandidate = matchingBeans.get(autowiredBeanName);} else {// We have exactly one match.Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}
标记为 Lazy 的属性
如果有标记为 @Lazy 的注入属性,Spring 并不会立即进行属性注入
// 获取 @Lazy 的注入属性Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {// ★★★ 关键代码:解析依赖result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;
