上篇博客,经过AbstractAutowireCapableBeanFactory的doCreateBean方法中的createBeanInstance方法,通过反射调用无参构造器来实现对象的创建,并且将创建的对象封装在BeanWrapper中。
但此时仅仅完成了对象的创建,对象还需要进行属性的注入以及对象的初始化,下面继续分析对象的属性注入方法和初始化方法,暂时不涉及代理类的创建。
属性的注入,主要发生在doCreateBean方法中的populateBean方法中
可以发现,此刻对象的属性还均为null,在进入这个方法之前,我们知道,Spring对于属性的注入有几种方式。
第一种为构造注入,显然一定是发生在对象创建的过程中,因此poplateBean中不包含构造注入的代码,第二种为自动注入,即使用Autowired属性,实现自动注入,当前开发基本不会使用,因此我们只关注第三种注入的方式,即set注入。
同时,set注入的两种实现方式,一种为xml形式的
另一种为注解形式的开发,即使用@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再细细研究。
至此,对象创建完毕。