不贴代码,Spring的Bean实例化过程应该是怎样的? 两个阶段 容器启动阶段 Bean实例化阶段
不贴代码,Spring的Bean实例化过程应该是怎样的?
这里我们并不会详细的分析源代码,只是给出Spring在完成哪些工作的时候使用到了什么类,这些类具体的职责都是什么,如果我们要弄清楚Spring Bean实例化的内幕与详细信息,那么可以看哪些源代码? 至于具体的详细的代码信息,大家可以查看Spring相关类的代码。
两个阶段
容器启动阶段 Bean实例化阶段
容器启动阶段
1、配置元信息
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
相当于:
Role role=new Role();
role.setId(1);
role.setRoleName("工程师");
role.setNote("重要人员");-->
<property name="id" value="1"/>
<property name="roleName" value="工程师"/>
<property name="note" value="重要人员"/>
</bean>
2、BeanDefination
3、BeanDefinationReader
4、BeanDefinationRegistry
5、BeanFactoryPostProcessor
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
<property name="maxWait" value="${jdbc.maxWait}"></property>
<property name="minIdle" value="${jdbc.minIdle}"></property>
<property name="driverClassName"
value="${jdbc.driverClassName}">
</property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
Bean实例化阶段
1、对象创建策略
关于策略模式有不了解的可以查阅相关书籍,或者网上相关资料,这是设计模式相关的内容,本文主要关注Bean实例化的整体流程,设计模式相关知识不在讨论。
2、BeanWrapper——对象的外衣
3、设置对象属性
对于基本类型的属性,如果配置元信息中有配置,那么将直接使用配置元信息中的设置值赋值即可,即使基本类型的属性没有设置值,那么得益于JVM对象实例化过程,属性依然可以被赋予默认的初始化零值。 对于引用类型的属性,Spring会将所有已经创建好的对象放入一个Map结构中,此时Spring会检查所依赖的对象是否已经被纳入容器的管理范围之内,也就是Map中是否已经有对应对象的实例了。如果有,那么直接注入,如果没有,那么Spring会暂时放下该对象的实例化过程,转而先去实例化依赖对象,再回过头来完成该对象的实例化过程。
这里有一个Spring中的经典问题,那就是Spring是如何解决循环依赖的? 这里简单提一下,Spring是通过三级缓存解决循环依赖,并且只能解决Setter注入的循环依赖,请大家思考一下如何解决?为何只能是Setter注入?详细内容可以查阅相关博客,文档,书籍。
4、检查Aware相关接口
例如ApplicationContext继承自ResourceLoader和MessageSource,那么当我们实现ResourceLoaderAware和MessageSourceAware相关接口时,就将其自身注入到业务对象中即可。
5、BeanPostProcessor前置处理
6、自定义初始化逻辑
7、BeanPostProcess后置处理
8、自定义销毁逻辑
9、使用
10、调用回调销毁接口
需要指出,容器启动阶段与Bean实例化阶段之间的桥梁就是我们可以选择自定义配置的延迟加载策略,如果我们配置了Bean的延迟加载策略,那么只有我们在真实的使用依赖对象的时候,Spring才会开始Bean的实例化阶段。而如果我们没有开启Bean的延迟加载,那么在容器启动阶段之后,就会紧接着进入Bean实例化阶段,通过隐式的调用getBean方法,来实例化相关Bean。
(完)