我是靠谱客的博主 优美香水,最近开发中收集的这篇文章主要介绍Spring源码系列(十八)Spring创建Bean的过程(七),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.写在前面

笔者前面已经讲了属性注入的元数据的获取,今天笔者带着大家继续往下讲,今天主要讲的是属性注入的源码。

2.属性注入

废话不多说,,继续接着上篇博客来讲剩下代码,具体的代码如下:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
    //这个值一般的情况下都是等于true
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isTraceEnabled()) {
			logger.trace("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
        //于是会执行这个方法
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		populateBean(beanName, mbd, instanceWrapper);
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

    //省略一部分代码....
	return exposedObject;
}

上面的earlySingletonExposure一般情况下都是等于true,除非这个要创建的bean不是单例的,或者将allowCircularReferences的值给改了(默认是true),Spring在生成BeanDefinition的时候已经赋给这个变量值了,你可以通过BeanFactoryPostProcessor来实现对它的修改,那么这个if判断中执行的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));是干嘛的?这儿是用来处理循环依赖的,由于笔者在前面的博客已经介绍,在这笔者就不多赘述,读者可以看笔者的这篇博客《Spring源码系列(七)Spring中的循环依赖》既然这个弄明白了,那继续看剩下的代码,也就是我们今天要讲的重点的方法populateBean(beanName, mbd, instanceWrapper);这个方法就是完成属性注入的,具体的代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //判断bean的包装对象是不是等于null,等于null直接结束
	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.
    // 在设置属性之前,给所有InstantiationAwareBeanPostProcessor机会修改bean的状态。例如,它可以用于支持字段注入的样式。
    // 前提的条件不是合成的方法
    // 提供的一个扩展的地方
    //hasInstantiationAwareBeanPostProcessors 这个值只要有InstantiationAwareBeanPostProcessor的bean的后置处理器就为ture
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
	}

	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();
		}
		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) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

2.1实例化后的后器处理

由于上面的属性的注入的方法太长,所以笔者这儿将这个属性注入分开来讲,先来看Spring在调用属性注入的时候调用Bean的后置处理器是干嘛的?具体的代码如下:

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
				return;
			}
		}
	}
}

这儿是调用是InstantiationAwareBeanPostProcessor的Bean的后置处理器中的postProcessAfterInstantiation方法,先来看下Spring这个时候bean的后置处理器中有那几个是这个类型的bean的后置处理器,还是先看下Bean后置处理器的机构图,具体的如下:

在这里插入图片描述

看来这儿Bean的后置处理器主要有三个是实现InstantiationAwareBeanPostProcessor接口,分别是ImportAwareBeanPostProcessorCommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor

走来先看ImportAwareBeanPostProcessorpostProcessAfterInstantiation方法,具体的代码如下:

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
	return true;
}

可以发现是直接返回true,没有做任何处理。

笔者再带着大家看CommonAnnotationBeanPostProcessorpostProcessAfterInstantiation方法,具体的代码如下:

public boolean postProcessAfterInstantiation(Object bean, String beanName) {
	return true;
}

发现这儿也是返回true,没有做任何处理。

最后再来看下AutowiredAnnotationBeanPostProcessorpostProcessAfterInstantiation方法,具体的代码如下:

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
	return true;
}

同样也是返回true,没有做任何处理。

那么可能有读者会问,那spring提供这个干嘛?这儿是提供给读者来扩展的,就是在属性注入之前,有机会修改bean的状态。例如,它可以用于支持字段注入的样式。

2.2自动注入

继续看剩下的代码,具体的代码如下:

//是否设置属性,对应的xml中的prototype标签,我们这儿是没有设置,直接是null
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

//获取装配模型,我们这儿没有设置对应的自动装配模型,所以这儿是0
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
//这个if是不进的,但是我们要搞懂源码这个判断中执行的代码还是要看
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    //创建MutablePropertyValues对象
	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;
}

上面的代码就是新获取对应的自动装配的模型,由于我们这儿没有设置对应的自动装配的模型,但是看源码,还是要搞懂吧!按照姓名自动装配调用的方法是autowireByName(beanName, mbd, bw, newPvs);具体的代码如下:

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

    //获取所有set方法的后缀,
    //举个例子,例如有个setA()方法,取出来就是a
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    //遍历刚才找出来的propertyNames
	for (String propertyName : propertyNames) {
        //判断spring容器中是否包含这个bean
		if (containsBean(propertyName)) {
            //获取这个bean
			Object bean = getBean(propertyName);
            //添加到MutablePropertyValues
			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");
			}
		}
	}
}

可以发现按照姓名自动装配的规则就是看set方法后缀在spring容器中有没有这个名称的bean,如果有就直接添加到MutablePropertyValues对象中,那么查找的规则是调用unsatisfiedNonSimpleProperties(mbd, bw);方法,具体的代码如下:

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
	Set<String> result = new TreeSet<>();
    //获取自己设置的属性
	PropertyValues pvs = mbd.getPropertyValues();
    //获取所有属性的描述符,就是包括get和set的方法,同时父类的也会查找出来
	PropertyDescriptor[] pds = bw.getPropertyDescriptors();
	for (PropertyDescriptor pd : pds) {
        //是set方法
        //没有别的依赖
        //自己设置的属性中没有包含获取到的属性描述符
       	//同时也不是简单类型
		if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
				!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
			result.add(pd.getName());
		}
	}
	return StringUtils.toStringArray(result);
}

查找的规则就是,首先查找这个类的所有的get或set方法,然后判断这个方法是set方法同时没有别的依赖和自己设置的属性中没有包含获取到的属性描述符同时也不是简单类型,这个时候就会添加到set集合中,最后转成数组传出去。所以按照名称自动装配,这个名称就是set方法的后缀

我们再来看下按类型自动装配,主要调用的是autowireByType(beanName, mbd, bw, newPvs);方法,具体的代码如下:

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

    //获取自定义的类型转换器
	TypeConverter converter = getCustomTypeConverter();
    //若没有就用默认的
	if (converter == null) {
		converter = bw;
	}

    //自动装配的bean的名称
	Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //和前面一样的,返回的是set方法同时没有别的依赖和自己设置的属性中没有包含获取到的属性描述符同时也不是简单类型
	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类型的注入没有意义,直接排除掉
			if (Object.class != pd.getPropertyType()) {
                //获取spring的自定义的方法参数对象
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				// Do not allow eager init for type matching in case of a prioritized post-processor.
                //同时也排除PriorityOrdered
                //在优先处理后处理器的情况下,请勿让PriorityOrdered进行类型匹配
				boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                //创建依赖的描述
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                //获取对应的依赖项,也就是B,与set方法的参数类型有关,和set方法的后缀无关
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
                    //添加到MutablePropertyValues
					pvs.add(propertyName, autowiredArgument);
				}
				for (String autowiredBeanName : autowiredBeanNames) {
                    //注册对应的依赖的bean
					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);
		}
	}
}

和按照名称自动注入的查找规格是一样的,但是注入的规则不一样,按照名称注入,这个名称就是set方法的后缀,而按照类型注入的话,与set方法的后缀没有关系,只与set方法的类型有关。

2.3后置处理属性

笔者继续带大家看剩下的代码,具体的代码如下:

//这个值默认为true
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//是否需要深度检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
    //这个值只有在自动装配上或者自己设置了属性的时候才不为空
	if (pvs == null) {
		pvs = mbd.getPropertyValues();
	}
    //调用对应的bean的后置处理器
	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;
		}
	}
}

从前面写的内容可以得出这儿是InstantiationAwareBeanPostProcessor类型的bean的后置处理器有三个,分别是ImportAwareBeanPostProcessorCommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor

走来先看ImportAwareBeanPostProcessorpostProcessProperties的方法,具体的代码如下:

public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
	// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
	// postProcessProperties method attempts to autowire other configuration beans.
	if (bean instanceof EnhancedConfiguration) {
		((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
	}
	return pvs;
}

上面的代码就是判断这个是不是cglib的代理的类,也就是我们自己写的配置类,然后给它设置一个BeanFactory属性,这儿对于我们普通类的作用不大,直接跳过。

继续看CommonAnnotationBeanPostProcessorpostProcessProperties方法,具体的代码如下:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //这个代码上篇博客讲过,由于我们之前找了一次,这儿就会从缓存中去
	InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
	try {
        //进行属性的注入
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
	}
	return pvs;
}

上面的代码调用的时候会进行属性注入,同时将我们传进来的PropertyValues的值也传入到inject方法中去了,具体的代码如下:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Processing injected element of bean '" + beanName + "': " + element);
			}
			element.inject(target, beanName, pvs);
		}
	}
}

上面的代码就是遍历之前找的InjectedElement,然后调用element.inject(target, beanName, pvs);进行属性的注入,具体的代码如下:

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
			throws Throwable {
	if (this.isField) {
		Field field = (Field) this.member;
		ReflectionUtils.makeAccessible(field);
		field.set(target, getResourceToInject(target, requestingBeanName));
	}
	else {
		if (checkPropertySkipping(pvs)) {
			return;
		}
		try {
			Method method = (Method) this.member;
			ReflectionUtils.makeAccessible(method);
			method.invoke(target, getResourceToInject(target, requestingBeanName));
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}
}

如果是属性就通过反射设置属性,如果是方法就通过反射调用方法。至此@Resource注解的属性或方法就处理完成了。

继续看AutowiredAnnotationBeanPostProcessorpostProcessProperties方法,具体的代码如下:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //这个笔者之前有讲过这个方法,主要是找@Autowired注解
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
        //调用属性注入的方法
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

上面是调用属性注入的方法metadata.inject(bean, beanName, pvs);具体的代码如下:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //前面已经找好的属性
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
    //遍历所有的属性,进行对应的属性注入
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Processing injected element of bean '" + beanName + "': " + element);
			}
			element.inject(target, beanName, pvs);
		}
	}
}

上面的代码主要遍历所有的属性,进行属性注入,主要是调用element.inject(target, beanName, pvs);方法,具体的代码如下,这儿分成是两种情况,一种是属性,一种是方法,笔者先带着大家看下属性,具体的代码如下:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //获取这次要注入的属性
	Field field = (Field) this.member;
	Object value;
    //是否有缓存,有缓存的话直接从缓存中取出
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
        //依赖的描述信息
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        //设置class
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
		Assert.state(beanFactory != null, "No BeanFactory available");
        //获取类型转换器
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
            //查找这个要填充的属性
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if (value != null || this.required) {
                    //设置到缓存中
					this.cachedFieldValue = desc;
                    //注册对应的依赖的bean
					registerDependentBeans(beanName, autowiredBeanNames);
					if (autowiredBeanNames.size() == 1) {
                       	  //自动注入的名称
						String autowiredBeanName = autowiredBeanNames.iterator().next();
                        //判断这个注入的属性在spring容器中是否存在
						if (beanFactory.containsBean(autowiredBeanName) &&
								beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                            //存入缓存
							this.cachedFieldValue = new ShortcutDependencyDescriptor(
									desc, autowiredBeanName, field.getType());
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
                //缓存的标志位设置成true,表示已经缓存起来了
				this.cached = true;
			}
		}
	}
    //通过反射进行设置值
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		field.set(bean, value);
	}
}

上面的代码是在进行属性注入,主要注入的是属性,同时spring会进行一些检查,查看这个属性是否存在spring容器中,如果这些检查成功后,直接将这个属性的信息存入到缓存中,同时将这个缓存的标志位设置成true,便于下次直接从缓存中去,而不是再去查找一遍,最后通过反射将这个属性设置进去,最后再来看下方法的,具体的代码如下:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //判断是否需要跳过
	if (checkPropertySkipping(pvs)) {
		return;
	}
    //获取这次的方法
	Method method = (Method) this.member;
	Object[] arguments;
    //判断是否有缓存
	if (this.cached) {
		// Shortcut for avoiding synchronization...
		arguments = resolveCachedArguments(beanName);
	}
	else {
        //方法的参数的个数
		int argumentCount = method.getParameterCount();
		arguments = new Object[argumentCount];
        //依赖的描述信息
		DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
		Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
		Assert.state(beanFactory != null, "No BeanFactory available");
        //获取类型转换器
		TypeConverter typeConverter = beanFactory.getTypeConverter();
        //遍历所有的参数
		for (int i = 0; i < arguments.length; i++) {
			MethodParameter methodParam = new MethodParameter(method, i);
			DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
			currDesc.setContainingClass(bean.getClass());
			descriptors[i] = currDesc;
			try {
                //查找对应参数
				Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
                //查找出来的参数是空,同时也是非必须的,直接设置为null
				if (arg == null && !this.required) {
					arguments = null;
					break;
				}
                //查找出来直接设置
				arguments[i] = arg;
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
			}
		}
		synchronized (this) {
			if (!this.cached) {
				if (arguments != null) {
					DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
                    //注册依赖的Bean
					registerDependentBeans(beanName, autowiredBeans);
                    //如果方法参数个数等于自动注入的参数个数,证明全部找到
					if (autowiredBeans.size() == argumentCount) {//存入对应的缓存
						Iterator<String> it = autowiredBeans.iterator();
						Class<?>[] paramTypes = method.getParameterTypes();
						for (int i = 0; i < paramTypes.length; i++) {
							String autowiredBeanName = it.next();
							if (beanFactory.containsBean(autowiredBeanName) &&
									beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
								cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
										descriptors[i], autowiredBeanName, paramTypes[i]);
							}
						}
					}
					this.cachedMethodArguments = cachedMethodArguments;
				}
				else {
					this.cachedMethodArguments = null;
				}
				this.cached = true;
			}
		}
	}
    //通过反射调用对应的方法
	if (arguments != null) {
		try {
			ReflectionUtils.makeAccessible(method);
			method.invoke(bean, arguments);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}
}

上面的代码是在进行加@Autowired注解的方法的调用过程,走来先是查找对应方法参数,先是查看缓存中时候有,如果有直接使用缓存中的数据,如果没有,就需要从spring容器中查找,如果查找不到的话,同时这个@Autowired的require的值是true的话,这儿调用resolveDependency方法会直接报错,,但是如果@Autowired的require的值是false的话,没有找到的参数就会返回null,同时方法不会调用,这两种情况都是会存到spring的缓存中去的。最终调用的方式都是通过反射调用。

你会发现上面调用的后置处理器都没有改变pvs的值,也就是说如果前面已经找到了对应pvs,这个执行bean后置处理器中的判断pvsToUse的值就不会等于null,这种也就是在自动注入的情况下满足,于是笔者关掉的自动注入,再来看这最后一小部分的代码,具体的如下:

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;

但是关闭了自动注入,这个值还是不等于null,因为走来如下的代码就进行对应的初始化

if (pvs == null) {
	pvs = mbd.getPropertyValues();
}

那么spring这段代码的意义何在?于是笔者点开了postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);具体的如下:

在这里插入图片描述

发现这个方法已经弃用了,所以这儿就可以不用管了。

2.4应用属性的值

还有最后一部分的代码,具体的如下:

//判断是否需要检查
if (needsDepCheck) {
	if (filteredPds == null) {
		filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
	}
	checkDependencies(beanName, mbd, filteredPds, pvs);
}

//这个方法肯定执行
if (pvs != null) {
	applyPropertyValues(beanName, mbd, bw, pvs);
}

上面执行检查的代码,不是我们的重点,我们直接看applyPropertyValues(beanName, mbd, bw, pvs);方法,具体的代码如下:

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;

	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);
			}
		}
        //将其转成ArrayList
		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);

	// 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();
            // 如果originalValue=AutowiredPropertyMarker
			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);
			}
			// 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);
			}
            //非动态的String非集合或者数组
			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();
	}

	// Set our (possibly massaged) deep copy.
	try { //调用对应的set方法进行设置值
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}

上面的代码,走来判断这个属性是否转换过,如果转换就直接设置值,如果没有就需要转换,转换完了直接通过set方法的方法设置对应的,于是属性注入就讲完了。

2.5总结

属性注入,先调用的是BeanPostProcessorpostProcessAfterInstantiation的方法,判断这个类是否需要属性注入,在然后就是判断是否是自动注入,根据自动注入的类型,找出对应的set方法,同时返回对应的属性列表,然后调用BeanPostProcessorpostProcessProperties的方法,完成属性注入,先是完成加了@Resource的注解属性注入和方法的调用,然后再完成加了@Autowired的注解的属性注入和方法的调用,最后再将前面获取的属性的列表进行赋值,都是调用对应的set方法进行设置,而加了@Resource注解和加了@Autowired注解属性的注入和方法的调用都是通过反射进行调用的。

3.写在最后

本篇博客主要讲了属性注入,同时属性注入中也设置到了循环引用,笔者在这儿没有讲了,因为笔者前面的博客《Spring源码系列(七)Spring中的循环依赖》这篇博客中笔者已经讲清楚了,如果不清楚的话,可以去看下这篇博客。后面spring的内容还有一点点。

最后

以上就是优美香水为你收集整理的Spring源码系列(十八)Spring创建Bean的过程(七)的全部内容,希望文章能够帮你解决Spring源码系列(十八)Spring创建Bean的过程(七)所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部