基于 Spring Framework v5.2.6.RELEASE
接上篇:Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)
概述
前两篇文章分析了 AutowiredAnnotationBeanPostProcessor 后处理器的 determineCandidateConstructors
和postProcessMergedBeanDefinition
方法,本文分析最后一个关键的方法postProcessProperties
。
本文的内容非常依赖上一篇文章中的内容,因此强烈建议先阅读之前的文章。
postProcessProperties
方法的调用时机,是在早期 Bean 实例被创建之后、执行属性注入之前,此时,通过调用postProcessProperties
方法,可以对即将注入的属性和属性值做一些处理。
postProcessProperties
方法
进入postProcessProperties
方法的源码。
// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertiespublicPropertyValuespostProcessProperties(PropertyValuespvs, Objectbean, StringbeanName) { InjectionMetadatametadata=findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationExceptionex) { throwex; } catch (Throwableex) { thrownewBeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } returnpvs; }
首先,通过findAutowiringMetadata方法获取注入元信息,这个方法在上一篇做过详细的介绍,而且,上一篇介绍的postProcessMergedBeanDefinition
在此时已经被调用过了,所以,这里可以直接从缓存中获取到注入元信息。
关于注入元信息metadata
中的详细内容,也可以参考上一篇文章,这里就不错做介绍了。
上一篇传送门:Spring 源码阅读 41:AutowiredAnnotationBeanPostProcessor 分析(2)
接下来,调用了metadata
的inject
方法,并在最后将参数重传入的pvs作为方法的返回值返回。所以,这里的inject
是处理逻辑的关键方法,而被处理的对象就是pvs
,也就是要给 Bean 实例注入属性的属性值。
InjectionMetadata 的inject
方法
我们进入inject
方法。
// org.springframework.beans.factory.annotation.InjectionMetadata#injectpublicvoidinject(Objecttarget, StringbeanName, PropertyValuespvs) throwsThrowable { Collection<InjectedElement>checkedElements=this.checkedElements; Collection<InjectedElement>elementsToIterate= (checkedElements!=null?checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElementelement : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '"+beanName+"': "+element); } element.inject(target, beanName, pvs); } } }
在inject
方法中,首先声明了一个elementsToIterate
变量,如果当前元信息对象的checkedElements
成员变量不是空,那么elementsToIterate
的值就是checkedElements
,如果是空,则这个值是injectedElements
。
此处的两个集合,依然需要参考上一篇文章中介绍过的内容,这里做简单的回顾。injectedElements
指的是 Spring 从当前处理的 Bean 类型中找到的所有被标记了属性注入注解的非静态的属性和方法。checkedElements
是injectedElements
中被注册到相应的 BeanDefinition 的externallyManagedConfigMembers
中的元素。
有了要处理的数据之后,如果elementsToIterate
不为空,则遍历其中的每一个 InjectedElement 对象,进行处理。处理的逻辑在 InjectedElement 的inject
方法中。
InjectedElement 的inject
方法
进入inject
方法。
// org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#injectprotectedvoidinject(Objecttarget, StringrequestingBeanName, PropertyValuespvs) throwsThrowable { if (this.isField) { Fieldfield= (Field) this.member; ReflectionUtils.makeAccessible(field); field.set(target, getResourceToInject(target, requestingBeanName)); } else { if (checkPropertySkipping(pvs)) { return; } try { Methodmethod= (Method) this.member; ReflectionUtils.makeAccessible(method); method.invoke(target, getResourceToInject(target, requestingBeanName)); } catch (InvocationTargetExceptionex) { throwex.getTargetException(); } } }
因为每一个 InjectedElement 对象都是一个属性或者方法,这里将需要注入值的属性和方法分开处理。
如果是一个属性,则获取到对应的 Field 对象,调用field.set
设置属性;如果是一个方法,则将要设置的属性值作为参数调用method.invoke
执行这个方法。这样,属性注入就完成了。
在上面的方法中,不管是属性还是方法,在注入值的时候,都会通过getResourceToInject方法获取要注入的值,这个方法其实就是从 BeanFactory 容器中查找对应的 Bean 实例对象。
总结
本文介绍了 AutowiredAnnotationBeanPostProcessor 的postProcessProperties
方法的源码,分析了 Spring 是如何查找通过注解注入的属性值的。至此,AutowiredAnnotationBeanPostProcessor 后处理器的源码分析就结束了。