有关Spring对象的属性赋值与初始化---getBean(“beanName“)

上篇博客,经过AbstractAutowireCapableBeanFactory的doCreateBean方法中的createBeanInstance方法,通过反射调用无参构造器来实现对象的创建,并且将创建的对象封装在BeanWrapper中。

但此时仅仅完成了对象的创建,对象还需要进行属性的注入以及对象的初始化,下面继续分析对象的属性注入方法和初始化方法,暂时不涉及代理类的创建。

属性的注入,主要发生在doCreateBean方法中的populateBean方法中

可以发现,此刻对象的属性还均为null,在进入这个方法之前,我们知道,Spring对于属性的注入有几种方式。

第一种为构造注入,显然一定是发生在对象创建的过程中,因此poplateBean中不包含构造注入的代码,第二种为自动注入,即使用Autowired属性,实现自动注入,当前开发基本不会使用,因此我们只关注第三种注入的方式,即set注入。

同时,set注入的两种实现方式,一种为xml形式的

<bean id="" class="">
    <property></property>
</bean>
JDK <property name="" value=""></property>
自建 <property name="" ref=""></property>

另一种为注解形式的开发,即使用@Value、@Autowired、@Inject、@Resources的形式进行开发,@Value就等同于对JDK类型的注入,@Autowired的就等同于对自建类型的注入。我们分别对其展开讨论,先是基于xml形式的开发的属性注入。

 其中id为Integer类型,name和password都是String类型。

 此段代码均为安全校验或一些极少使用的情况,不做具体分析了就。

 pvs里边装载的是从BeanDefinition中取出的对象的属性名和对应的要注入的属性值,下面一段是关于自动注入的代码,我们不分析。直接Alt+F9。

 hasInstAwareBpps,如果为true,表明是根据注解的方式,来给成员变量赋值(@Autowire @Value),为False就是基于注解进行开发。

显然此时为false。

 needsDepCheck是是否开启校验,很少使用这个属性。

 很显然我们进入最下边的分支

 创建一个original对象,用于存储未发生过类型转换的原始对象。

此处进行判断,是否经历过类型转换,如果经历过就不需要再进行转换,直接将属性注入,返回即可,这里是第一次获取对象,显然没有经历过转换。此时original里装载的是未发生过转换的属性。

 

之后是获取类型转换器。

 如果有用户的自定义类型转换器,就使用用户自定义的类型转换器,否则类型转换器就为bw,即BeanWrapper,前文有提,BeanWrapper中存有系统提供的类型转换器。

valueResolver是对四个入参的封装,便于后续使用。

下面代码就是遍历所有的原始属性,对其进行类型转换,转换为对象属性真正的类型,此时要注入的属性为Address,即用户自定义类型的属性,因此此时他的原始属性为RuntimeBeanReference,JDK类型的为另一种属性。

进入resolveValueIfNecessary方法,用户自定义类型在此方法进行类型转换

 强转之后执行resolveReference方法,其实我们推测,对于用户自定义类型的属性的赋值,最终一定会调用FactoryBean.getBean("address")方法。下面验证我们的猜想。

 不出我们所料,先获取refName,再getBean方法,获取对象,最终将对象返回,完成类型转换。

再进行Id属性的类型转换,此时我们发现,JDK类型的原始类型为TypedStringValue,并且JDK完成类型转换的代码与自定义类型的不同。

 经历上段代码,从最原始的 TypedStringValue 类型转变为“1”,即String类型(String类型可能也不对),并不是我们想要的Integer类型。

 在此处才被真正被转换完成,convertible是考虑到对象为final等情况。

 转换完成后,设置标志位,标志着这个属性已经转换完成了。

for循环结束后,全部类型转换完成,进行属性的注入,此时我们推断,一定是根据反射获取对象的set方法,再通过set进行属性注入。

 

执行完这个方法之后,将转换完毕的属性,对属性进行赋值,至此,属性注入结束,下面进行有关注解形式的属性赋值。

Account对象

Product对象 

 配置

 开始创建,断点打在poplulateBean上。

 但是因为我们使用的是应用上下文的接口实现,因此会创建一些其他干扰类(可能不太合适),并不单单只创建一个Product对象,因此要设置条件断点。

 开始执行,只关注与xml配置文件形式开发不同的部分。

基于注解的属性注入是以BeanPostProcess实现的,具体为其中的 AutowiredAnnotationBeanPostProcessor 这个实现的属性注入

 可以看到,此时的hasInstAwareBpps为true

 循环遍历所有的BeanPostProcessor,直到找到AutowiredAnnotationBeanPostProcessor 后开始属性的注入。

调用其中的inject方法。

 挨个获取,之后注入,根本上与xml配置一样。

 从配置文件中获取对应属性的值。

 值若不为空,则通过反射进行注入。

下面进行初始化方法,主要与

 

 此方法有关,因为其中涉及到AOP,除此之外很简单,就不debug了,简单说明里边方法涉及的功能即可,具体到AOP再细细研究。

至此,对象创建完毕。 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值