21、Spring5.x源码之旅二十一getBean详解七

  • DefaultListableBeanFactory的doResolveDependency解析依赖
  • DefaultListableBeanFactory的findAutowireCandidates寻找自动装配类型
    • addCandidateEntry添加到候选集合里
  • DependencyDescriptor的resolveCandidate

DefaultListableBeanFactory的doResolveDependency解析依赖

继续上篇的,如果是我们自己定义的类型的参数,没有懒加载注解的,就会进行解析。
首先看BeanFactiry是否有添加快捷方式,一般没有,除非子类继承扩展,然后看是否有注解方法设置的参数的值,有的话就设置处理。否则的话就判断是否是多个bean的注入,比如参数类型是集合。最后才是获取自动装配类型的对象findAutowireCandidates,如果找到多个的话,会进行优先级来选取,然后进行装配类型对象的创建,这里的创建又是一个getBean的过程,但是也可能是直接获取,一般来说是主要看工厂方法的定义顺序,因为内部可以用了ASM处理,但是如果有重名的,就乱序了,具体为什么不行可以看ConfigurationClassParserretrieveBeanMethodMetadata方法,不过影响也不大,反正都能自动装配好。创建好了再判断类型是否匹配,最后返回。下面我们来分析几个主要的方法,主要的理解了,其他的自己慢慢了解就行。

	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
   
     
		//设置注入点,并获得前一个注入点,以便后面可以设置回来
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
   
     //解析快捷方式,存在就返回,子类BeanFactiry可以扩展,默认null
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
   
     
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);//获取注解可能的值
			if (value != null) {
   
     
				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());
				try {
   
     
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
   
     
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
			//是否是多个bean的注入,比如参数类型是集合,map
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
   
     
				return multipleBeans;
			}
			//寻找装配候选对象
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
   
     
				if (isRequired(descriptor)) {
   
     //空的话,又是必须的,才会报异常
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;//自动装配的bean名字
			Object instanceCandidate;//装配实例

			if (matchingBeans.size() > 1) {
   
     //有多个
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
   
     
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
   
     
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
   
     

						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
   
     //只有一个
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
   
     
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
   
     //获取装配实例,也要进行getBean过程
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
   
     
				if (isRequired(descriptor)) {
   
     //不存在,又是必须
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
   
     //类型不匹配
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
   
     //处理完后恢复当前注入点
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

DefaultListableBeanFactory的findAutowireCandidates寻找自动装配类型

这里会去寻找我们的容器里面是否有参数的类型,先把参数类型的bean定义中的所有bean名字找出来,创建一个LinkedHashMap集合,然后判断类型是不是内部的类型,是的话也要加进去。然后遍历候选名字集合,把非自引用的可以作为别人依赖的类型添加到集合中,如果集合为空,还要进行处理判断,比如是不是数组类型,集合类型,再做相应处理。

protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
   
     
		//获取requiredType对应的bean名字数组
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
		for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
   
     //如果是依赖内部一些类的类型
			Class<?> autowiringType = classObjectEntry.getKey();
			if (autowiringType.isAssignableFrom(requiredType)) {
   
     
				Object autowiringValue = classObjectEntry.getValue();
				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);//非自引用,且可以为其他类做自动装配的,就加入集合
			}
		}
		if (result.isEmpty()) {
   
     //空的处理
			boolean multiple = 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) &&
						(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
   
     
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
			if (result.isEmpty() && !multiple) {
   
     
				// Consider self references as a final pass...
				// but in the case of a dependency collection, not the very same bean itself.
				for (String candidate : candidateNames) {
   
     
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
   
     
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
	}

addCandidateEntry添加到候选集合里

如果是多元素集合和StreamDependencyDescriptor类型的,会去创建相应的bean,然后放入,否则就直接把类型放入进来。

private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
			DependencyDescriptor descriptor, Class<?> requiredType) {
   
     

		if (descriptor instanceof MultiElementDescriptor) {
   
     
			Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
			if (!(beanInstance instanceof NullBean)) {
   
     
				candidates.put(candidateName, beanInstance);
			}
		}
		else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
				((StreamDependencyDescriptor) descriptor).isOrdered())) {
   
     
			Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
			candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
		}
		else {
   
     
			candidates.put(candidateName, getType(candidateName));
		}
	}

DependencyDescriptor的resolveCandidate

当我们解析出来要装配的类型的时候,就可以开始去真正的获取该类型的对象了,其实内部还是调用getBean的。

	public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {
   
     

		return beanFactory.getBean(beanName);
	}

大致的流程就分析到这里啦,很多细节还没深入,因为比较复杂,还是先把大致搞清楚在去琢磨细节比较好。下篇我们把基本的流程图总计下。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。