Spring源码分析六:Bean加载之populationBean③

(一)序言

在spring源码分析加载bean之doGetBean②分析里面doCreateBean中简单提到了populateBean属性注入,本文将对属性注入进行详细分析,笔者如有分析错误,还请及时指出。

(二)bean属性注入:populateBean

1、属性注入代码逻辑:populateBean

AbstractAutowireCapableBeanFactory类中的doCreateBean方法中实例化bean完成后,紧接着执行populateBean(beanName,mbd,instanceWrapper);进行属性注入,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 {
			// 实例化的对象是空且没有任何属性则直接结束
			return;
		}
	}
	/**
	 * 在属性设置前执行InstantiationAwareBeanPostProcessors后置处理器,调用postProcessAfterInstantiation方法可以加工bean
	 * 不同的是,在createBean中已经调用过InstantiationAwareBeanPostProcessors->postProcessBeforeInstantiation方法
	 */
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				//bean如果实现了InstantiationAwareBeanPostProcessor,则会执行重写的postProcessAfterInstantiation方法
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
	}
	//bean自动注入的方式:按名称注入和按类型注入
	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);
		// 根据名称自动注入
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// 根据类型自动注入
		if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}
	//是否有InstantiationAwareBeanPostProcessor后置处理器
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	//是否需要检查依赖
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		//执行后置处理器InstantiationAwareBeanPostProcessor中的postProcessProperties方法和postProcessPropertyValues方法
		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);
	}
}

2、属性注入整体流程

(1)是否需要执行InstantiationAwareBeanPostProcessor后置处理器中的postProcessorAfterInstantiation方法,主要是用户自行扩展且可以控制bean注入是否需要继续属性填充;
(2)根据注入类型,分为按名称注入和按类型注入,将需要依赖的bean提取存储到MutablePropertyValues
newPvs对象中的propertyValueList变量中,具体类型是PropertyValue;
(3)InstantiationAwareBeanPostProcessor后置处理器中的postProcessProperties和postProcessPropertyValues方法,在属性注入前对注入的属性进行再次处理;
(4)将PropertyValues中的属性都填充到BeanWrapper。

(三)属性注入中的核心方法

1、按名称注入:autowireByName

获取当前bean中的注入属性,并通过属性的bean名称去加载bean,最后将属性注册,代码逻辑如下:

 protected void autowireByName(
   	String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
   	//寻找bw中需要被注入的bean属性
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
           //检查缓存中是否已包含属性bean
		if (containsBean(propertyName)) {
			Object bean = getBean(propertyName);//去加载bean(递归)
			pvs.add(propertyName, bean);//将bean属性存储到pvs
			//注册依赖:Map<String, Set<String>>类型的dependentBeanMap和dependenciesForBeanMap变量中
			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");
			}
		}
	}
}

2、按类型注入:autowireByType(较复杂)

先获取属性bean,然后对需要依赖注入的属性bean获取set方法,紧接着对属性bean进行类型匹配(最复杂、核心),将所有需要被依赖注入的属性进行注册,代码如下:

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);
	//寻找需要依赖注入的bean属性
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		try {
		    //获取属性描述符
			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
			if (Object.class != pd.getPropertyType()) {
			    //获取属性bean的set方法
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				//将bean属性类型匹配到的值存储到autowiredBeanNames中(核心)
                   //这里的返回值是真正的需要注入的属性,autowiredBeanNames是需要注入的属性(可能是集合)的names
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
					pvs.add(propertyName, autowiredArgument);//添加待注入的bean列表中
				}
				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);
		}
	}
}

3、匹配类型bean:(do)resolveDependency(doXX核心)

(1)@Autowired注解是在AutowiredAnnotationBeanPostProcessor中注入时会被调用;
(2)ConstructorResolver->autowireConstructor在resolveAutowiredArgument(methodParam,beanName,autowiredBeanNames,converter,fallback);代码执行过程时,也会调用resolveDependency方法。

DefaultListableBeanFactory->resolveDependency代码如下:

 public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
		Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	//处理不同的bean属性类型
	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 {
	    //处理懒加载的bean,若是,则创建代理对象,否则将执行通用类型的依赖处理
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
		    //处理通用类型的依赖,熟悉的doXX方法
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

Spring开发常用依赖注入类型由DefaultListableBeanFactory->doResolveDependency掌控,其主要核心步骤如下:

(1)resolveEmbeddedValue对占位符的替换即@Value注解的${};
(2)解析依赖属性即流stream、数组Array、集合Collection和Map类型;
(3)spring根据三大顺序(@Primary、@Priority和fallback匹配)从多个实例中选择一个作为将要注入的实例;
(4)检查匹配出来的实例与实际类型是否相符合。

DefaultListableBeanFactory->doResolveDependency具体代码如下:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
	@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  //利用重写了ThreadLocal的NamedThreadLocal来设置当前注入点,提高安全性,进行隔离
  InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  try {
  /**
   * 仅ShortcutDependencyDescriptor重写了resolveShortcut方法且在AutowiredFieldElement、AutowiredMethodElement->inject使用到,
   * 只有解析@Autowired、@Value注解的元素才会用到,作用是避免重复解析、使用缓存存储,提升注入性能
   */
      Object shortcut = descriptor.resolveShortcut(this);
      //shortcut这个值实际上是由beanFactory.getBean(this.shortcut, this.requiredType)加载获取的
      if (shortcut != null) {
          return shortcut;
      }
      //缓存中没有该bean,则开始执行类型匹配逻辑
      Class<?> type = descriptor.getDependencyType();
      //用于获取@Value注解的值,如@Value(value = "${xx.yy}")
      Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
      //此时的value是${xx.yy}这个值,spring的SPEL表达式未被替换
      if (value != null) {
          if (value instanceof String) {
              /**
                * resolveEmbeddedValue该方法很复杂,找对方法实现类就简单,核心思想就是替换占位符${}
                * (1)AbstractBeanFactory中的resolveEmbeddedValue方法
                * (2)PropertySourcesPlaceholderConfigurer->processProperties中的valueResolver匿名内部方法->resolveRequiredPlaceholders
                * (3)AbstractPropertyResolver->createPlaceholderHelper创建正则表达式替换,placeholderPrefix前缀和placeholderSuffix后缀
                * (4)AbstractPropertyResolver->doResolvePlaceholders执行正则表达式进行占位符替换
                */
              String strVal = resolveEmbeddedValue((String) value);
              BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                      getMergedBeanDefinition(beanName) : null);
              //解析Spring中的SPEL表达式
              value = evaluateBeanDefinitionString(strVal, bd);
          }
          //获取类型转换器
          TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
          try {
              //将解析出来的bean,转换为type类型
              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()));
          }
      }
      //解析依赖的是流stream、数组Array、集合Collection和Map类型的属性
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
          return multipleBeans;
      }
      //查找所有type类型的实例,将其使用键值对存储在matchingBeans变量中,String为:实例对应的beanName,Object为实例
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
          if (isRequired(descriptor)) {
              //注解中添加了required=true时,若没找到则抛异常
              raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          return null;
      }
      String autowiredBeanName;
      Object instanceCandidate;
      //matchingBeans大于1,说明Spring中找到了多个该type类型的实例
      if (matchingBeans.size() > 1) {
      /**
       * spring从多个实例中按照一定的顺序选择一个作为注入的实例
       * (1)被标识为@primary的bean
       * (2)挑标识为@Priority且优先级最高的bean。可以不标识,一旦标识,不允许同一优先级的存在
       * (3)fallback依赖的名称与matchingBeans中任意一Key匹配
       */
          autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
          if (autowiredBeanName == null) {
              if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                  //在选择实例时为空且非集合类的bean匹配到多个将报非唯一性错误
                  return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
              }else {
                  return null;
              }
          }
          //从matchingBeans中获取对应的类型匹配结果中的实例
          instanceCandidate = matchingBeans.get(autowiredBeanName);
      }else {
          //程序走到这里代表只有唯一的一个type实例
          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) {
          // 确保instanceCandidate是bean的实例,前面matchingBeans中的Object有可能是实例或类类对象
          instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
      if (result instanceof NullBean) {
          if (isRequired(descriptor)) {
              //该依赖属性是NullBean且required=true未找到时报错
              raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
          }
          result = null;
      }
      //匹配到的类型和实际type是否想匹配
      if (!ClassUtils.isAssignableValue(type, result)) {
          throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
      }
      return result;
  }finally {
      //更新注入点
      ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  }
}

4、依赖注入:applyPropertyValues

applyPropertyValues是populateBean属性注入的最后一步,也是前面一系列选择实例、后置处理器对属性进行加工后,将属性存储,到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());
	}
	MutablePropertyValues mpvs = null;
	List<PropertyValue> original;
	//populateBean方法中如果正常获取到的属性是存储在MutablePropertyValues中,如果存在则直接注入
	if (pvs instanceof MutablePropertyValues) {
		mpvs = (MutablePropertyValues) pvs;
		if (mpvs.isConverted()) {//是否被转换过
			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());//获取未转换的原始值
	}

	TypeConverter converter = getCustomTypeConverter();//获取类型转换器
	if (converter == null) {
		converter = bw;
	}
	//创建一个BeanDefinition的处理器
	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

	//创建一个变量进行深拷贝
	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();
			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;
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}
			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);
	}
}

(四)属性注入总结

(1)InstantiationAwareBeanPostProcessors后置器的postProcessAfterInstantiation实例化后方法控制bean是否需要进行后续属性注入;
(2)解析依赖属性并根据配置采用哪种注入方式,XML中可使用default-autowire="byName"指定按名称AUTOWIRE_BY_NAME或按类型AUTOWIRE_BY_TYPE注入;
(3)InstantiationAwareBeanPostProcessor后置器的postProcessPropertyValues方法对依赖属性进行注入前处理;
(4)applyPropertyValues注入属性,前面将属性处理、加工得到的属性注入到bean的依赖属性中。

说明
(1)按名称注入AUTOWIRE_BY_NAME:主要就是从Spring中加载bean即getBean方法;
(2)按类型注入AUTOWIRE_BY_TYPE:主要是处理@Value注解以及配置的property、自动装配@Autowired的实现类提取注入,DefaultListableBeanFactory->doResolveDependency具体核心点如下:

(1)resolveEmbeddedValue对占位符的替换即@Value注解的${};
(2)解析依赖属性即流stream、数组Array、集合Collection和Map类型;
(3)spring根据三大顺序(@Primary、@Priority和fallback匹配)从多个实例中选择一个作为将要注入的实例;
(4)检查匹配出来的实例与实际类型是否相符合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

进击的猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值