我是靠谱客的博主 粗暴母鸡,这篇文章主要介绍Spring源码:bean创建(五)解决依赖一、resolveDependency二、搜索类型匹配的bean列表,现在分享给大家,希望可以做个参考。

一、resolveDependency

在上一节最后,Spring将与获取指定相匹配的所有bean,其实现就在BeanFactory的resolveDependency中,下面是DefaultListableBeanFactory中实现:

复制代码
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
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); //对于Java8中Optional类的处理 if (javaUtilOptionalClass == descriptor.getDependencyType()) { return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName); } //对于前面讲到的提早曝光的ObjectFactory的特殊处理 else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } //javaxInjectProviderClass的特殊处理 else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName); } else { //如果字段上带有@Lazy注解,表示进行懒加载 //Spring不会立即创建注入属性的实例,而是生成代理对象,来代替实例 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { //通用处理逻辑 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }

在上面代码中,Spring主要是先对特殊类型进行处理,如果依赖的属性是需要懒加载的话,还对生成代理对象来满足要求,最后才是通用逻辑的处理:

复制代码
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { //Spring在第一次创建依赖的bean时,会保存该bena的beanName作为shortcut //在第二次创建时,就可以直接根据beanName调用getBean方法,不需要再根据类型来重新查询一遍 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } //注入属性的类型 Class<?> type = descriptor.getDependencyType(); //处理@Value注解------------------------------------- //获取@Value中的value属性 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { //解析value if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); //如果需要会进行类型转换后返回结果 return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } //------------------------------------- //对数组、容器类型的处理 //因为是数组或容器,Sprng可以直接把符合类型的bean都注入到数组或容器中,处理逻辑是: //1.确定容器或数组的组件类型 //2.调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例) //3.将符合beanNames添加到autowiredBeanNames中 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } //对非数组、容器对象的处理 //获取所有类型匹配的Map(beanName -> bean实例) Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); //结果为空 if (matchingBeans.isEmpty()) { //如果配置了required属性为true(默认值也是true)的话,抛出异常 if (descriptor.isRequired()) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; //如果类型匹配的bean不止一个,Spring需要进行筛选,筛选失败的话抛出异常 if (matchingBeans.size() > 1) { autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (descriptor.isRequired() || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(type, matchingBeans); } else { return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { //只有一个bean与类型匹配,那么直接使用该bean Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } //如果获取到instanceCandidate是Class类型 //那么还需要beanFactory.getBean(autowiredBeanName, instanceCandidate)来获取bean的实例 //否则直接返回bean return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate); } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }

上面代码的处理过程:

  1. Spring注入依赖后会保存依赖的beanName,作为下次注入相同属性的捷径。如果存在捷径的话,直接通过保存的beanName获取bean实例
  2. 对@Value注解的处理。如果存在,会获取并解析value值
  3. 对数组或容器类型的处理。如果是数组或容器类型的话,Spring可以将所有与目标类型匹配的bean实例都注入进去,不需要判断。
    1. 获取数组或容器单个组件的类型
    2. 调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
    3. 保存类型匹配的beanNames
  4. 非数组、容器类型的处理
    1. 调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
    2. 如果类型匹配的结果为多个,需要进行筛选:Spring源码分析:多个bean同时满足注入条件时,spring的选择
    3. 如果筛选结果不为空,或者只有一个bean类型匹配,就直接使用该bean

二、搜索类型匹配的bean列表

根据注解进行依赖注入的主要工作,就是根据标注的字段的类型来搜索符合的bean,并将类型匹配的bean注入到字段中。而搜索bean的工作在findAutowireCandidates方法中实现:

复制代码
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
protected Map<String, Object> findAutowireCandidates( String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { //获取类型匹配的bean的beanName列表 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); //存放结果的Map(beanName -> bena实例) Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length); //如果查找的类型是特殊类型或其子类的话,也将保存好的特殊类型的实例放到结果集中 for (Class<?> autowiringType : this.resolvableDependencies.keySet()) { if (autowiringType.isAssignableFrom(requiredType)) { Object autowiringValue = this.resolvableDependencies.get(autowiringType); autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType); if (requiredType.isInstance(autowiringValue)) { result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); break; } } } for (String candidate : candidateNames) { //不是自引用 && 符合注入条件 if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } //结果集为空 && 注入属性是非数组、容器类型 //如果条件满足,Spring会放宽注入条件的限制 if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { // FallbackMatch:放宽对泛型类型的验证 DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } if (result.isEmpty()) { // 如果结果还是为空,Spring会将自引用添加到结果中 for (String candidate : candidateNames) { if (isSelfReference(beanName, candidate) && (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && isAutowireCandidate(candidate, fallbackDescriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } } } return result; }

代码步骤:

  1. 将获取类型匹配的Bean工作交给BeanFactoryUtils.beanNamesForTypeIncludingAncestors。该方法除了当前beanFactory还会递归对父parentFactory进行查找
  2. 如果注入类型是特殊类型或其子类,会将特殊类型的实例添加到结果
  3. 对结果进行筛选
    1. BeanDefinition的autowireCandidate属性,表示是否允许该bena注入到其他bean中,默认为true
    2. 泛型类型的匹配,如果存在的话
    3. Qualifier注解。如果存在Qualifier注解的话,会直接比对Qualifier注解中指定的beanName。需要注意的是,Spring处理自己定义的Qualifier注解,还支持javax.inject.Qualifier注解
  4. 如果筛选后,结果为空,Spring会放宽筛选条件,再筛选一次

1.BeanFactoryUtils.beanNamesForTypeIncludingAncestors

复制代码
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
public static String[] beanNamesForTypeIncludingAncestors( ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { //通过ListableBeanFactory的getBeanNamesForType方法来获取类型匹配的beanName列表 String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit); //如果当前BeanFactory是HierarchicalBeanFactory,即支持父BeanFactory的功能 //Spring会对其父BeanFactory进行搜索 if (lbf instanceof HierarchicalBeanFactory) { HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf; //对父BeanFactory搜索的前提:父BeanFactory也是ListableBeanFactory if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) { String[] parentResult = beanNamesForTypeIncludingAncestors( (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit); List<String> resultList = new ArrayList<String>(); resultList.addAll(Arrays.asList(result)); for (String beanName : parentResult) { //排除掉已经添加的beanName if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) { resultList.add(beanName); } } result = StringUtils.toStringArray(resultList); } } return result; }

可以看到,获取beanName集合的功能是在ListableBeanFactory定义的,上面代码除了调用该方法,还会对父BeanFactory进行递归的搜索(HierarchicalBeanFactory提供父BeanFactory功能的支持)。

DefaultListableBeanFactory即继承了ListableBeanFactory,又继承了HierarchicalBeanFactory。

下面是DefaultListableBeanFactory对ListableBeanFactory功能的实现:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { //如果type为null,ResolvableType.forRawClass(type)会返回Object.class if (!isConfigurationFrozen() || type == null || !allowEagerInit) { return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit); } //先尝试从缓存中获取 Map<Class<?>, String[]> cache = (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType); String[] resolvedBeanNames = cache.get(type); if (resolvedBeanNames != null) { return resolvedBeanNames; } //获取结果后再放入缓存(如果安全的话,对ClassLoader的验证,避免Class是由不同ClassLoader加载的,而造成类型不匹配的问题) resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true); if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) { cache.put(type, resolvedBeanNames); } return resolvedBeanNames; }

2.doGetBeanNamesForType

上面代码是对获取的BeanName提供了缓存的功能,具体的搜索操作交给了doGetBeanNamesForType完成:

复制代码
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
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { List<String> result = new ArrayList<String>(); //Spring会遍历所有beanDefinitionNames for (String beanName : this.beanDefinitionNames) { // 筛选掉bean的别名,只会对bean的id进行操作 if (!isAlias(beanName)) { try { RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 验证BeanDefinition的完整性 if (!mbd.isAbstract() && (allowEagerInit || ((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) && !requiresEagerInitForType(mbd.getFactoryBeanName()))) { // 是否是FactoryBean boolean isFactoryBean = isFactoryBean(beanName, mbd); //获取BeanDefinition装饰的BeanDefinition,如果有的话 BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); //非工厂bean的判断 boolean matchFound = (allowEagerInit || !isFactoryBean || (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) && (includeNonSingletons || (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) && isTypeMatch(beanName, type); if (!matchFound && isFactoryBean) { // 工厂bean的判断 beanName = FACTORY_BEAN_PREFIX + beanName; matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type); } if (matchFound) { //如果条件符合,添加到结果集 result.add(beanName); } } } //catch 略 } } // 对手动添加的单例beanName进行搜索 for (String beanName : this.manualSingletonNames) { try { // 与前面逻辑相同,分为工厂bean和普通bean两种情况进行判断 if (isFactoryBean(beanName)) { if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { result.add(beanName); continue; } beanName = FACTORY_BEAN_PREFIX + beanName; } if (isTypeMatch(beanName, type)) { result.add(beanName); } } //catch 略 } return StringUtils.toStringArray(result); }

为了实现获取特定类型的bean,Spring会遍历所有已保存的beanName(不包括别名),对每个beanName对应的bean定义进行判断,将符合的beanName添加到结果集中

 

 

 

 

 

 

最后

以上就是粗暴母鸡最近收集整理的关于Spring源码:bean创建(五)解决依赖一、resolveDependency二、搜索类型匹配的bean列表的全部内容,更多相关Spring源码:bean创建(五)解决依赖一、resolveDependency二、搜索类型匹配内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部