属性注入(populateBean)

处理 @Autowired 和 @Resource 标记的属性和方法(这里的方法不包括构造方法,因为构造方法在前面已经完成了推断)

问题:@Autowired 是 byType?,再 byName?

流程:

  1. 根据需要注入的类型找到所有的 beanName
  2. 遍历 beanName,找到需要注入的类型,并放入一个集合中(待推断)
    1. 如果待注入集合中只有一个符合条件的 class,则表示找到了要注入的 bean
    2. 如果带注入集合中有多个符合条件的 class,则继续按名称推断
      1. 看看有没有标记为 @Primary 注解的 bean,有则返回
      2. 判断有没有 @Priority 注解的 bean,有的话,返回值低的优先级作为 bean 返回
      3. 看看是不是有别名 bean 符合,有的话作为 bean 返回
      4. 如果都不满足,则抛出异常 NoUniqueBeanDefinitionException
  3. 根据 beanName 从单例池中获取所需要注入的 bean
  4. 利用反射完成属性注入

调用后置处理器

这里的后置处理器必须是 InstantiationAwareBeanPostProcessor 类型

  1. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  2. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  3. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  4. // ★★★ 关键代码:进行属性填充
  5. // CommonAnnotationBeanPostProcessor 完成对 @Resource 属性的注入
  6. // AutowiredAnnotationBeanPostProcessor 完成对 @Autowired 属性的注入
  7. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  8. if (pvsToUse == null) {
  9. if (filteredPds == null) {
  10. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  11. }
  12. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  13. if (pvsToUse == null) {
  14. return;
  15. }
  16. }
  17. pvs = pvsToUse;
  18. }
  19. }

查找类的注入元数据(包括属性,方法)

根据当前要进行属性填充的 bean,找到当前 bean 需要注入的元数据(属性和方法)

  1. // ★★★ 获取需要注入的元数据
  2. // 1、查找标记有 @Autowired 的 field
  3. // 2、查找标记有 @Autowired 的 method
  4. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

根据类型查找

matchingBeans 很关键,先根据类型查找,看存在多少相同类型的 bean

  • beanName:当前需要进行属性注入的 bean
  • type:当前注入的属性的类型
  • descriptor:当前注入的属性的包装,包括字段名称,类型,是不是方法等信息
    1. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

根据名称查找

  1. // ★★★ 如果找到多个符合条件的 bean
  2. // matchingBeans.size() > 1:则说明通过类型查找找到了多个符合条件的 bean
  3. if (matchingBeans.size() > 1) {
  4. // ★★★ 关键代码:开始根据名称进行推断,根据 descriptor 提供的 fieldName 来推断 autowiredBeanName
  5. // 由此可以推断,@Autowired 是先根据类型查找,如果找到多个,再根据名称查找
  6. // 此处根据需要注入的属性的名字推断,查找真正需要注入的 bean
  7. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  8. if (autowiredBeanName == null) {
  9. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  10. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  11. }
  12. else {
  13. // In case of an optional Collection/Map, silently ignore a non-unique case:
  14. // possibly it was meant to be an empty collection of multiple regular beans
  15. // (before 4.3 in particular when we didn't even look for collection beans).
  16. return null;
  17. }
  18. }
  19. // ★ 从多个匹配的对象中根据 autowiredBeanName 获取 bean
  20. instanceCandidate = matchingBeans.get(autowiredBeanName);
  21. } else {
  22. // We have exactly one match.
  23. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  24. autowiredBeanName = entry.getKey();
  25. instanceCandidate = entry.getValue();
  26. }

标记为 Lazy 的属性

如果有标记为 @Lazy 的注入属性,Spring 并不会立即进行属性注入

  1. // 获取 @Lazy 的注入属性
  2. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
  3. descriptor, requestingBeanName);
  4. if (result == null) {
  5. // ★★★ 关键代码:解析依赖
  6. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  7. }
  8. return result;