Spring源码解析之-AbstractAutowireCapableBeanFactory#populateBean详解

一、介绍

Spring 如何将Bean 的属性依赖关系注入Bean 实例对象中的,本章主要分析

AbstractAutowireCapableBeanFactory#populateBean

Spring 版本:5.2.10.RELEASE

二、源码及流程分析

2.1 populateBean 方法 流程图及步骤

在这里插入图片描述
主要步骤为:

  1. 先判断 是否BeanWrapper 是否为null, 如果为null ,并且有属性,那就报错
  2. 判断是否 是合成的,并且是否有 InstantiationAwareBeanPostProcessor 类型的后置处理器需要处理,如果需要,那就 执行对应的 postProcessAfterInstantiation 方法
  3. 根据注入类型判断 是否需要 按照 ByName 还是 ByType 注入
  4. 判断是否有 InstantiationAwareBeanPostProcessor 类型的后置处理器需要处理,如果需要,那就 执行对应的 postProcessProperties 方法 ,这个方法主要是对 相关注解 属性的处理,详见 spring源码解析之—InstantiationAwareBeanPostProcessor解析
  5. 判断是否有依赖dependency-check ,以及相关的依赖检查 ,详细在后面介绍
  6. 进行属性转换和填充,详细下面解释

2.2 源码分析

2.2.1 populateBean方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        // 校验,如果为null 并且有属性值,抛出异常
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// 跳过空实例的属性填充阶段
				return;
			}
		}

		/**
		这里是判断是否有 hasInstantiationAwareBeanPostProcessors ,并且是系统自定义的(没有代理) 这样就可以再填充属性之前 还有机会 进行一些调整
		主要就是运行 postProcessAfterInstantiation 实例化(不是初始化)之后的后置处理器
		*/
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 这里需要留意有一个 返回 false , 那就直接返回
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}
        /**
         获取属性, MutablePropertyValues 类型
         PropertyValues接口的默认实现。允许对属性进行简单的操作,并提供构造函数来支持从Map中进行深度复制和构造
        */
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        // 获取注入类型,默认是0(AUTOWIRE_NO),如果不是by_name或者 by_type, 那就不走以下逻辑
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		    // by_type 或者 by_name 类型,先 深度拷贝 一个对象
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			//根据名称注册
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			//根据类型注册
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		
		/**
		判断是否需要依赖检查
		dependency-check 是在spirng 2.x 里面使用的属性,用来指定是否需要检验 属性是否赋值, 但是在 spring 3.x + 以后的
		版本已经放弃了, 后续的版本建议在 setter 方法上使用@Required ,但是 @Required在 spring 5.1 之后的版本又被废弃了
        dependency-check 有四种类型,none (默认就是none), simple,object,all 
       所以当前版本是 5.2.10.RELEASE, 个人认为这里应该是默认的 none, needsDepCheck  为false
	    这里 加这类的判断,应该是为了兼容以前的配置吧
		**/
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
			    /**
			     这里主要是 来 对 @Resource , @Autowired, @Value ,@Inject 等注解 进行 
                 注入,这里主要是两个类CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor 
                 详细的内容可以查看上面的解释
			    **/
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
						   /**
						    对属性进行过滤, 这里主要是过滤三种
						    1. CGLIB method 代理的需要过滤掉
						    2.  需要忽略掉的类型, 比如 String 
						    3.  需要过忽略的接口类型, 比如 一些Aware  类型的接口
						   */
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						// postProcessPropertyValues 已经被放弃了, 这样应该是出于兼容性的考虑
						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) {
		    // 填充属性,详细过程下面详细解释
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

2.2.2 dependency-check

在 Bean创建的时候,有时需要强制检测属性是否已经赋值, 这里就可以使用dependency-check .

dependency-check 是在 spring 2.x 里面有的,spring 3 + 后续都没有了,有时源码里面 可能为了兼容以前的版本,有一定的冗余代码,既然源码里面涉及到了,我们就 简单了解一下.
dependency-check 一共有4个类型:

  • none :不检查,默认就是 none
  • simple :只检查简单类型属性以及集合类型属性
  • objects :检查除简单类型属性以及集合类型属性外的引用类型属
  • all : 所有类型

此外我们在spring 5.2.10.RELEASE 里面,即使配置 了spring-beans-2.5.xsd ,也是不能使用这个标签的,

在这里插入图片描述
spring在加载xsd文件时总是先试图在本地查找xsd文件(spring的jar包中已经包含了所有版本的xsd文件),如果没有找到,才会转向去URL指定的路径下载。spring的jar包里,在META-INF目录下都有一个spring.schemas,这里指定了对应的文件路径,这里将所有的版本都指向了本地的spring-beans.xsd ,但是本地的spring-beans.xsd 是没有支持这个 属性的

在这里插入图片描述
可以用 @Required注解 代替, 详细可见Spring源码解析之–@Required详解

2.2.3 filterPropertyDescriptorsForDependencyCheck

有一些版本 没有这个方法, 主要就是忽略过滤掉一些 属性的注入

  • CGLIB method 代理的需要过滤掉
  • 需要忽略掉的类型
  • 需要过滤掉的接口类型, 类似一些 Aware ,如 BeanNameAware
    比如AbstractAutowireCapableBeanFactory 构建的时候,就会加一下 需要忽略的依赖接口类型,ignoreDependencyType 的范围比 ignoreDependencyInterface 的范围大一些.
    在这里插入图片描述

2.2.4 postProcessProperties

InstantiationAwareBeanPostProcessor 里面有一个 对带有注解的属性 进行注入,这里主要 是两个类

2.2.5 autowireByName方法

大致思路:

  1. 获取需要依赖注入的属性
  2. 对属性进行遍历, 首先判断是否已经包含在 容器中(包括未初始化完成的,排查 BeanFactory类型)
  3. 获取对应的Bean ,放入到pvs 里面,并完善 器对应的依赖和被依赖关系
    autowireByName 过程还是比较简单的, 就是通过 name 去容器中获取(调用getBean),容器中 的缓存就是 用 bean name 作为key
	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        //返回bw 中需要依赖注入的属性,unsatisfiedNonSimpleProperties 详细解析如下
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		// 对属性进行遍历
		for (String propertyName : propertyNames) {
            /** 判断容器里面是否包含对应的bean,详细判断在后面
             如果存在,那就取出并加入pvs 里面.
             注册依赖关系,  主要是 放入dependentBeanMap  和 dependenciesForBeanMap 中
             其中 dependentBeanMap : 是当前bean被引用依赖的 bean
             dependenciesForBeanMap  :当前Bean所依赖的Bean的集合
            **/
			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");
				}
			}
		}
	}

	@Override
	public boolean containsBean(String name) {
	    // 对beanName  进行最终转换
		String beanName = transformedBeanName(name);
		/** 判断容器中是否 含有 beanName对应的 bean ,没有完全初始化完的也算
		 这里需要排除BeanFactory 类型 , factoryBean 类型的也算
		 如果没有找到,就去 父BeanFactory 里面寻找
		*/
		if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
			return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
		}
		// Not found -> check parent.
		BeanFactory parentBeanFactory = getParentBeanFactory();
		return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
	}

2.2.6 autowireByType方法

大致思路:

  1. 获取类型转换器,如果没有,默认为 bw
  2. 获取需要注入的属性
  3. 对所有属性进行遍历,开始 注入, 首先排除 Object.class 类型,调用resolveDependency 方法进行校验获取对应的最后的值
  4. 放入 pvs 里面,并 注册对应的依赖和被依赖关系
	protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        // 获取自定义的类型转换器, 如果为null, 那就 使用bw ,BeanWrapper 是继承了 TypeConverter 类型的
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		// 获取需要注入的 propertyNames 
		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.
				// 这里首先排除 Object.class 类型,毫无意义
				if (Object.class != pd.getPropertyType()) {
				    // 获取指定属性的setter 方法,包装成 MethodParameter 类型
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					//判断实例是否需要紧急加载,是否实现了PriorityOrdered接口
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					/**
					解析指定beanName的属性所匹配的值,并把解析到属性名称存储在
					autowiredBeanNames中当属性存在多个封装bean 时如:
					@Autowired private List<A> aList; 将会找到所有匹配A类型的bean 并将其注入, 详细流程在下面分析
					**/
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					//加入到 pvs里面
					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);
			}
		}
	}

2.2.7 unsatisfiedNonSimpleProperties方法

返回未满足要求的非简单bean属性数组

大致思想:

  1. 获取所有输入的属性
  2. 获取bw 里面所有的属性
  3. 遍历所有属性,返回未满足要求的非简单bean属性数组(不包含简单l类型属性,如字符串) ,如下4个条件
    3.1 setter 方法不为空
    3.2 确定给定的bean属性是否被排除在依赖性检查之外,这里主要是判断是否是CGLIB 代理的属性 ,是否在忽略依赖类型里面,是否是指定的忽略依赖接口
    3.3 给出的属性填充值里面是不是包括对应的属性名称
    3.4 属性是不是简单类型的属性
	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		// 获取所有输入的属性
		PropertyValues pvs = mbd.getPropertyValues();
		// 获取所有属性的描述
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		for (PropertyDescriptor pd : pds) {
            /** 
            这里便是判断是否满足条件
            1. 属性没有对应的setter 方法
            2. 确定给定的bean属性是否被排除在依赖性检查之外,这里主要是判断是否是CGLIB 代理的属性 ,是否在忽略依赖类型里面,是否是指定的忽略依赖接口
            3. 给出的属性填充值里面是不是包括对应的属性名称
            4. 属性是不是简单类型的属性
            */
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}
		return StringUtils.toStringArray(result);
	}
	
	/** 是否被排除在依赖性检查之外
	1. 判断此属性是否是CGLIB 代理的属性
	2. 是否在忽略依赖类型 ignoredDependencyTypes 里面
	3. 是否是指定的忽略依赖接口ignoredDependencyInterfaces 里面
	*/
	protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
		return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
				this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
				AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
	}

2.2.8 applyPropertyValues方法

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        // 如果属性列表为null,直接返回
		if (pvs.isEmpty()) {
			return;
		}

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

		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

        // pvs 默认是 MutablePropertyValues 类型,获取属性列表
		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			/**
			 判断属性是否已经转换过 ,如果已经转换过,直接赋值,并返回
			 */
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				try {
					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());
		}

        // 获取自定义转换类型,如果为null ,使用默认的bw, BeanWrapper 类继承了 TypeConverter 
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// 这里是创建一个 深度拷贝的list,解决值引用相关的问题
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
		    /** 如果子属性已经转换过,直接添加到 deepcopy list 里面
		     如果还没有转换,那就先获取
		    */
			if (pv.isConverted()) {
				deepCopy.add(pv);
			}
			else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				/**
				AutowiredPropertyMarker ,就是一个简单的标记类, 如果是 AutowiredPropertyMarker 类型,
				那就获取对应的set方法,在通过DependencyDescriptor  包装一下, 在后面的 resolveValueIfNecessary 方法里面进行
				解析转换
				*/
				if (originalValue == AutowiredPropertyMarker.INSTANCE) {
					Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
					if (writeMethod == null) {
						throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
					}
					originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
				}
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				//检查给定的属性是否可写, 或者检查属性是否是索引或嵌套的属性,比如a.b , 或者 [a,b]
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
				    // 进行类型转换
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);

				// 将转换转换的值保存在pv 里面,同时加到 深度拷贝list里面
				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) {
			mpvs.setConverted();
		}

		try {
		    // 这里就是 最后将转换后的值 进行赋值填充
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}

2.2.9 DefaultListableBeanFactory#resolveDependency方法

根据此工厂中定义的bean解析指定的依赖关系

	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

三、小结

大致分析了 属性填充方法populateBean 的流程和 源码.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直打铁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值