背景:
谈到Spring,最先想到的自然是SpringFrameWork,即Spring框架。而框架最为核心的内容,其实就是一个Bean容器。基于该容器之上,才有了context、aop、web等等其它模块的内容,所以搞清楚Bean容器的工作流程是非常有必要的。因此本文将结合自身的学习和理解,来谈一谈spring容器中Bean完整的生命周期是怎样的。
1. 创建前准备
1.1 BeanDefinition解析流程
在了解Bean的创建工作之前,我们需要先了解一下BeanDefinition。在spring容器中,对象的创建工作可分为两个阶段:
1.对象实例化:也就是我们通常说的new一个对象(但在容器中,是通过反射来进行实例化)。
2.对象初始化:完成对象属性填充,执行Aware接口需要实现的方法,以及初始化、后置处理工作等。
因此,大家需要思考一个问题:
无论是实例化还是初始化阶段,spring容器都会需要使用到这些bean的信息,如成员属性、构造方法、类的全限定名称等等。因此这一系列信息在容器创建工作开始之前,spring容器将这些信息通通解析封装成了BeanDefinition(见名知意,类的定义信息),即一个bean对应一个BeanDefinition。
也就是说,无论是通过xml文件配置bean,还是通过注解扫描的方式注入的Bean,都会首先被解析成一个BeanDefinition对象。而这里的解析工作都是由一个叫BeanDefinitionReader的接口完成。
综上,springbean创建前的解析流程大致如图:
1.2 BeanFactoryPostProcessor
在上一步骤获取到BeanDefinition对象之后,似乎看起来已经可以开始创建了,但是出于优秀的扩展性,spring的context模块在初始化容器时(传说中的refresh()方法),会执行一系列BeanFactorryPostProcessor的实现类。
如在xml文件中配置的数据源:<property name="jdbcUrl" value="${jdbc.url}" />
就是在这里将${jdbc.url}解析成配置文件里的值jdbc:mysql://localhost:3306/xxx。
2. 对象实例化
在得到beanName对应得BeanDefinition对象后,自然就能拿到bean的class对象,是的,一切都是那么的丝滑。
然后一顿反射
Constructor ctor = clazz.getDeclareContructor();
stor.newInstance();
是的,对象就这么出来了。
3. 对象初始化
看似对象已经创建完成了,其实故事这才开始。
在完成实例化阶段后,容器拿到的对象只是实例化,但未初始化的对象,因此我们可以称它为“半成品对象”。基于该半成品对象,还有以下一系列流程。
3.1 属性注入
属性注入,也就是我们常说的DI(依赖注入)。对应到源码中,就是这个方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
该步骤处理的内容,就是将bean所依赖的成员属性注入(setter)到对象里;如果注入的成员属性是个引用类型的对象,那么容器会进行递归创建该成员属性(实例化、初始化)。
// 省略getter、setter public class A { private class B; } public class B { private class A; }
那个熟悉的循环依赖问题就是在这里处理的(通过三级缓存)。
3.2 执行Aware接口实现类
所谓Aware接口,具体是干啥的呢?具体咱们可以参考上图BeanFactory源码里的一段注释,作用应该可以感受到了。也就是若某个Bean实现了某种Aware接口,那么在初始化阶段的这个位置,就会去执行对应的Aware接口的实现方法,通过该方法可以获得对应的属性。如BeanNameAware,那么通过该方法可以获取BeanName,再如BeanFactoryAware,通过该方法久可以获取BeanFactory。
从图种可以看到,这里有很多种Aware,但是在此阶段,只会执行三种:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,如图:
3.3 bean后置处理
bean的后置处理主要包含3个操作(其实就是上图initializeBean的内容):
1. 执行所有BeanPostProcessor实现类的postProcessBeforeInitialization()方法。
2. 依次执行InitializingBean的afterPropertiesSet()、自定义init()方法。有图为证...
3. 执行所有BeanPostProcessor实现类的postProcessAfterInitialization()方法。
方法到这,其实bean对象的创建工作(实例化、初始化)已经接近尾声,是一个完整对象了。但是,此处也是给aop模块留下了扩展入口。
aop对应的代理对象生成器AbstractAutoProxyCreator,其入口就是它的postProcessAfterInitialization()方法。
4. 总结
至此,springbean的对象创建已经完成。最后附上一张总体流程图(本人热衷抽象派)