Spring 源码笔记-2.7 根据类型寻找 bean

# 前言

Spring 装配 bean 有两种类型:autowireByNameautowireByType

autowireByName 通过名称查找很直接,就是我们一直在学的 getBean() 。

autowireByType 根据类型查找相比起来就要复杂一些了,《 Spring 源码深度解析 》 中有介绍过的部分我就不再重复贴了,但是书中遗漏了一处重要的部分—— findAutowireCandidates 查找所有合适的 bean,还有一处新版本 Spring 中升级的部分——如果只需要一个但是找出多个 bean 该怎么处理,今天我们先来学习第一部分。

# 正文

# 本函数要做什么

1
2
3
4
5
6
@RestController
@RequestMapping("/article")
public class ArticleController {
    @Autowired
    private ArticleService articleService;
}

在初始化 ArticleController 的过程中,我们要为其装配 ArticleService 。

忽略掉外面代码一层一层的包裹之后,我们走到 DefaultListableBeanFactory.findAutowireCandidates 这个函数中,要寻找合适的候选 bean 。由于可能会找到多个,因此返回结果是候选 bean 的名称和其对应实例构成的 Map 。

# 源码解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//三个参数的含义依次是 
// 正在解析的 beanName, 本例中即 "articleController"
// 需要装配的 bean 类型, 本例中即 ArticleService.class
// 对当前依赖关系的解析类,记录了 ArticleController 和 ArticleService 的依赖关系
protected Map<String, Object> findAutowireCandidates(String beanName,
   Class<?> requiredType,
 DependencyDescriptor descriptor) {
  
  //第一步就是查找出所有符合类型的 beanName 。
  //似乎第一句就干完全部逻辑了???稍后我们再详细分析这个方法。
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
  /**
   *	resolvableDependencies 记录了 依赖类型--具体装配值 的映射
   *  	遍历 resolvableDependencies。如果该类型是我们需要的类型(ArticleService),
   *	
   */
		for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
			if (autowiringType.isAssignableFrom(requiredType)) {
				Object autowiringValue = this.resolvableDependencies.get(autowiringType);
              //key值是我们需要的类型,但value值未必。
              //value可能是ObjectFactory,就得调用它的 getObject() 来获取真正的bean.
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
                  //如果类型匹配,则塞入result
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		for (String candidate : candidateNames) {
          //如果不是自己依赖自己 , 并且符合装配候选,就塞入result。
          //何为符合装配候选(isAutowireCandidate)呢?稍后我们再详细分析。
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
		// Consider fallback matches if the first pass failed to find anything...
          //如果之前一轮都没找到,则考虑回退匹配,什么是回退匹配?稍后再分析。
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidate : candidateNames) {
				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
//再执行一遍上面的方法。如果不是自己依赖自己,并且符合装配候选,就塞入result。
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
			if (result.isEmpty()) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
// 如果依然没找到结果,那么满足以下条件的也是我们的目标。
// 1.是自引用
// 2.依赖不是多元素依赖 或者 bean名和候选者名字不相等(这里就避免了自引用导致无限循环)
// 3.候选者符合回退匹配之后的装配候选
				for (String candidate : candidateNames) {
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
      }

看完主干自然还是有点迷糊,我们留下了三个问题要继续研究: