前言
如题所见,这篇文章主要是想要说一说bean对象实例化的过程,因为在Spring的学习中,我们会经常遇到很多在这个实例化流程中起作用的方法与结构,但是各种特性总是堆在一起,杂七杂八的,很难得到一个好的梳理。
由于是基于xml文件,所以有一些地方代码量可能会比较繁琐,但是这些东西重在理解嘛,能听懂比什么都好说bean是什么?
bean对象其实和我们在学习Spring前碰到的对象都差不多,只是bean对象是被交给了spring容器管理,就相当于有了spring容器这个约束,在一些特别的规定中变成了bean对象这一陌生的名字。
正是因为bean是被spring容器管理的对象,bean对象的实例化会受到spring容器的种种限制,而不像我们之前的对象,直接new就完事了。
实例化过程
1.加载xml配置文件,获取bean并封装
xml文件,是我们写 bean 配置的地方,在 AppliacationContext 对象被创建后,由于该对象的构造方法中具有代表xml文件的参数,所以这个对象可以直接对我们的xml文件进行解析,并获取其中的 bean,但是由于我们的bean标签内部还有一些比较 NB 的属性值,这些属性值可以改变这个 bean ,所以为了不遗漏这些属性,bean 会被封装成 beanDefinition 对象。
特别的,对于这些 NB 的属性值,有一些我需要单独拿出来和大家讲一下,如以下代码:看不懂可以看注释,我认为我写的还挺清楚的
<!-- 以此法获取的Bean 是 UserDao 对应的 Bean ,不能用于获取原类中其余的方法-->
<bean id="factory" class="Impl3.MyBeanFactory1" factory-method="setUserDao">
<constructor-arg name="name" value="dsa"></constructor-arg>
</bean>
<!-- * 这里与上面的区别在于下面这个创建的是 MyBeanFactory1 对象,
*
* 而上面由于工厂方法返回的是一个UserDao,所以实际上是 UserDao对应的bean-->
<bean id="factory1" class="Impl3.MyBeanFactory1"></bean>
<!-- 这里的factory-bean不能是 factory,只能是没用静态工厂方法创建对象的原生factory1-->
<!-- * 因为 factory-bean是表示这个对象可以由哪一个类获取,获取方法为 factory-method 中的方法-->
<bean id="factoryOb" factory-bean="factory1" factory-method="userDao" ></bean>
2. 将beanDefinition存储在一个Map中
beanDefinition是经过封装的 bean,在此时,它还不是一个对象,将beanDefinition存储进一个map,有利于对bean的统一化管理,特别的,在该map中,键值就是我们在定义bean时设置的名称。
但是当我们定义的bean中没有id时,会去找name属性中的名字,如果还没有,就会变成我们的class属性中的字符串,这点需要牢记
这个map可以在调试过程中发现,因为涉及源码和调试,这里不过多演示。
具体路径为applicationContext.beanFactory.beanDefinitionMap
3. ApplicationContext 底层遍历beanDefinitionMap,创建bean对象
到这里,才开始正式的对bean进行创建,关于底层的一些东西,我自己也不懂,这一步就这样过一下得了,不过应该是通过增强for进行循环的
4.将创建好的bean实例化对象,存储在一个Map中
这里作用和上面一样,都是为了更方便的进行统一化管理,在这个map中,键值依然是id值,但是内容就是Object类型了,这里需要注意一下
5.在执行getBean()方法时,从map中获取
到这里,整个流程就走完了,我们可以发现,bean的ID在整个流程中都起着很强大的作用。所以,一定不要忘记给bean取一个比较好的id,这样便于我们去跟着源码来进行分析
总结
额呃呃呃,没什么想总结的,就这样了。