Spring源码系列:依赖注入(三)-属性注入

前面文章中对依赖注入的触发和bean的创建做了学习记录,本文将来记录一下bean的属性注入过程。Bean的属性注入发生在这个类中,这类是用于bean工厂实现的Helper类,职责就是将bean定义对象中包含的值解析为应用于目标bean实例的实际值。

类中的方法包含了对所有注入类型的处理。所以本文主要围绕这个方法展开来说。

resolveValueIfNecessary方法

:给定一个PropertyValue,返回一个value,解析对工厂中其他bean的引用。 value可能是:

RuntimeBeanReference : 在解析到依赖的Bean的时侯,解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中。

ManagedList:用来保存它所管理的List元素,它可以包含运行时期的bean引用(将被解析为bean对象).

ManagedSet :用来保存它所管理的set值,它可以包含运行时期的bean引用(将被解析为bean对象)

ManagedMap :用来保存它所管理的map值,它可以包含运行时期的bean引用(将被解析为bean对象)

1、方法申明

argName :为其定义的参数的名称

value :要解析的值对象

2、RuntimeBeanReference

当在beanfactory中作为另外一个bean的引用时,作为属性值对象,将在运行时进行解析。 RuntimeBeanReference是在对BeanDefinition进行解析时生成的数据对象。

3、RuntimeBeanNameReference

当在beanfactory中作为另外一个bean名称的引用时,作为属性值对象,将在运行时进行解析。

4、BeanDefinitionHolder

解析BeanDefinitionHolder:包含具有名称和别名的BeanDefinition。BeanDefinitionHolder就是使用名称或者别名来保存BeanDefinition的。

5、BeanDefinition

解析纯粹的BeanDefinition

6、ManagedArray

包含运行时期的bean引用(将被解析为bean对象)

7、ManagedList,ManagedSet,ManagedMap

包含运行时期的bean引用(将被解析为bean对象)

8、ManagedProperties

ManagedProperties表示的是一个spring管理的属性实例,它支持父/子 definition的合并。

9、TypedStringValue

TypedStringValue保存的是一个类型的属性值。

10、作为表达式进行评估

将给定的值作为表达式进行评估。

在完成上述解析之后,已经为我们的依赖注入做好了准备。这是真正把Bean对象设置到它所依赖的另一个Bean的属性中去的地方,可以看到,处理的属性也是各式各样的。具体属性的注入是在之前提到的BeanWrapper接口的实现类BeanWrapperImpl的setPropertyValue方法来完成。

setPropertyValue方法

a、方法声明

这个方法是私有的,是BeanWrapperImpl实际处理的方法,其对外也提供了setPropertyValue的其它重载方法来提供服务。

b、PropertyTokenHolder是BeanWrapperImpl的内部类

在setPropertyValue方法中会根据tokens变量是否为null,有两个不同的分支。其中当tokens为null时,则会对属性名进行递归调用分析处理,返回分析处理后的BeanWrapImpl对象nestedBw。如果nestedBw==this,则会设置pv的resolvedTokens属性值,最后将调用nestedBw对象的设置属性值方法设置属性。来具体看看:

c、其中当tokens为null时,即对集合类的域进行注入

1、propValue为null

propValue为null

2、对array进行注入

对array进行注入

2、对list进行注入

对list进行注入

2、对map进行注入

对map进行注入

其中当tokens不为null时,即对非集合类的域进行注入

这里是核心的地方,取得注入属性的set方法,通过反射机制,把对象注入进去。

总结

通过上面的几篇分析我们大概的熟悉了Bean创建和对象依赖注入的一个过程,在这个过程中,spring需要根据Beandefinition中的信息来递归完成依赖注入。并且这些递归的入口都是getBean这个方法。

一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用;

另一个递归是在依赖注入时通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。

在对Bean的属性进行依赖注入时解析的过程也是一个递归的过程。这样就可以根据依赖关系,一层一层的完成Bean的创建和注入,直到最后完成当前Bean的创建。

参考

《Spring技术内幕》

https://www.cnblogs.com/davidwang456/p/4213652.html

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180208A07GD700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券