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

概述

一、resolveDependency

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

	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主要是先对特殊类型进行处理,如果依赖的属性是需要懒加载的话,还对生成代理对象来满足要求,最后才是通用逻辑的处理:

	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方法中实现:

	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

	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功能的实现:

	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完成:

	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二、搜索类型匹配的bean列表所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部