十五、Spring源码学习之populateBean方法

本文详细解释了Spring框架中AutowireCapableBeanFactory的populateBean方法,重点剖析了自动装配(@Autowired)的处理过程,包括依赖注入、名称匹配、类型匹配以及Bean后置处理器的作用。
摘要由CSDN通过智能技术生成

AbstractAutowireCapableBeanFactory#populateBean()方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		//这里是调用实例化后的后置处理器(还没有进行属性填充)
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}
		/**
		 * 下面的这段逻辑处理的是@AutoWired,后面在说  这里才是真正开始进行属性填充
		 */
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			/**
			 * 这里调用的又是bean的后置处理器,这里的后置处理器是在bean属性填充过后的bean后置处理器
			 * 这个后置处理器正在现在用的最多,spring内部定义的InstantiationAwareBeanPostProcessor实现了这个接口,主要处理的是
			 * @AutoWired的后置处理器,依赖注入的在这里调用的,最重要的是postProcessProperties这个方法
			 * 所以InstantiationAwareBeanPostProcessor的后置处理器方法postProcessProperties是处理@AutoWired @Resource注解的
			 * 这个方法后面讲
			 */
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					//这个方法也可以修改属性值
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						//这个方法可以修改属性值
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			//真正开始解析bean的属性值
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

autowireByName()方法

autowireByName() 方法是自动装配的一个实现,它的工作原理是基于 Bean 名称进行匹配和注入。具体地,它会查找当前 Bean 定义中所有需要注入的属性(通常是 setter 方法或者字段),然后尝试在 Spring 容器中查找具有相同名称的 Bean。如果找到了匹配的 Bean,那么它就会被注入到当前 Bean 的相应属性中。

下面是这个方法的一些关键点:

  • 查找需要注入的属性:autowireByName() 方法首先会查找当前 Bean 定义中所有需要注入的属性。这通常是通过查找 Bean 类中的 setter 方法或字段来完成的。
  • 基于名称匹配:对于每一个需要注入的属性,方法会检查其名称(通常是 setter 方法的名称或字段的名称),然后在 Spring 容器中查找具有相同名称的 Bean。例如,如果有一个名为 setDataSource(DataSource dataSource) 的 setter 方法,那么方法会尝试在容器中查找名为 dataSource 的 Bean。
  • 注入匹配的 Bean:如果找到了匹配的 Bean,那么方法会将其注入到当前 Bean 的相应属性中。这通常是通过调用 setter 方法或设置字段的值来完成的。
  • 处理依赖关系:注意,自动装配可能会引发依赖关系问题。例如,如果两个 Bean 相互依赖对方,并且都尝试通过自动装配来注入对方,那么这可能会导致循环依赖的问题。Spring 框架会尝试解决这些问题,但并非所有情况都能成功解决。
  • 可配置性:虽然 autowireByName() 是自动装配的一种实现,但 Spring 允许通过配置文件或注解来配置自动装配的行为。例如,你可以在 Bean 定义中设置 autowire 属性为 byName 来启用基于名称的自动装配。

需要注意的是,自动装配虽然方便,但也可能引入一些不可预见的问题。因此,在使用自动装配时,建议谨慎考虑其可能带来的影响,并确保对其进行充分的测试。在许多情况下,显式地定义依赖关系(例如,通过构造函数注入或 setter 方法注入)可能是一个更好的选择,因为它提供了更高的可见性和控制力。

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

autowireByType()方法

autowireByType() 是 Spring 框架中用于自动装配的另一种方法,它基于 Bean 的类型(by type)进行自动装配。与 autowireByName() 不同,autowireByType() 方法会查找容器中与当前 Bean 属性类型相匹配的 Bean,并将它们注入到相应的属性中。

以下是关于 autowireByType() 方法的一些详细解析:

  • 查找需要注入的属性:
    与 autowireByName() 类似,autowireByType() 方法首先会识别当前 Bean 定义中需要自动装配的属性。这通常是通过检查 Bean 类中的字段或查找具有特定注解(如 @Autowired)的 setter 方法或构造函数来完成的。
  • 基于类型匹配:
    对于每一个需要注入的属性,autowireByType() 方法会检查其类型,并在 Spring 容器中查找所有相同或兼容类型的 Bean。如果找到多个相同类型的 Bean,并且没有使用任何额外的限定符(如 @Qualifier 注解或 Bean 名称),Spring 将无法确定要注入哪个 Bean,并可能抛出一个异常。
  • 注入匹配的 Bean:
    当找到与属性类型匹配的 Bean 时,autowireByType() 方法会将其注入到当前 Bean 的相应属性中。这通常是通过调用 setter 方法或利用反射直接设置字段的值来完成的。
  • 处理多个匹配的 Bean:
    如果找到多个与属性类型匹配的 Bean,并且没有使用限定符来指定应该注入哪个 Bean,那么 autowireByType() 方法的行为可能会因 Spring 的版本和配置而异。在某些情况下,它可能会抛出一个异常,指示存在多个候选者而无法进行注入。在其他情况下,它可能会尝试使用其他策略(如基于 Bean 名称的优先级)来解决冲突。
  • 配置和自定义:
    与 autowireByName() 一样,autowireByType() 的行为可以通过 Spring 的配置文件或注解进行配置。例如,可以在 Bean 定义中设置 autowire 属性为 byType 来启用基于类型的自动装配。此外,还可以使用 @Autowired 注解在 Java 类中显式地指定哪些属性应该进行自动装配。
  • 注意事项:
    虽然 autowireByType() 提供了基于类型的自动装配功能,但它在某些情况下可能会引入问题。特别是当容器中存在多个相同类型的 Bean 时,没有明确指定要注入哪个 Bean 可能会导致不确定性或错误。因此,在使用 autowireByType() 时,建议仔细考虑其潜在的副作用,并确保使用限定符或其他机制来明确指定依赖关系。

总体而言,autowireByType() 是一种方便的自动装配机制,但使用它时需要谨慎,并确保对依赖关系有清晰的了解和控制。在大多数情况下,使用显式的依赖注入(如通过构造函数或 setter 方法注入)可能更为可靠和可维护。

protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				if (Object.class != pd.getPropertyType()) {
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						pvs.add(propertyName, autowiredArgument);
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isTraceEnabled()) {
							logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

applyPropertyValues()方法

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs.isEmpty()) {
			return;
		}

		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
		}

		//这个类是 PropertyValues 默认实现类
		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;//mbd 原始属性集合

		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				try {
					//如果mbd的属性已解析过,则将其设置到beanWrapper中,并返回
					bw.setPropertyValues(mpvs);
					return;
				}
				catch (BeansException ex) {
					throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
				}
			}
			original = mpvs.getPropertyValueList();
		}
		else {
			original = Arrays.asList(pvs.getPropertyValues());
		}

		//获取用户自定义的类型转换器
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;//没有则取beanWrapper ,他继承了TypeConverter 相当于默认的类型转换器
		}

		//bean 属性值解析器
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// Create a deep copy, resolving any references for values.
		//存储解析后的属性值
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {//已解析的无需再处理
				deepCopy.add(pv);
			}
			else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				//解析属性值
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				// 属性可写 && 不是嵌套(如foo.bar,java中用getFoo().getBar()表示)或者索引(如person.addresses[0])属性
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}
				// Possibly store converted value in merged bean definition,
				// in order to avoid re-conversion for every created bean instance.
				if (resolvedValue == originalValue) {
					if (convertible) {
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				}
				else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				}
				else {
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			//标记当前bean 的属性都已解析完成 防止重复解析
			mpvs.setConverted();
		}

		// Set our (possibly massaged) deep copy.
		try {
			//最终将解析好的属性值集合设置到beanWrapper中
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}
  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值