Spring 是一个轻量级的 J2EE 开源框架,其目标是下降企业级应用开发难度,提升企业级应用开发效率。在日程开发中,咱们会常用 Spring 框架去构建应用。因此做为一个常用的框架,了解其原理仍是颇有必要的。接下来咱们就从宏观层面上,来看看 Spring 中的 bean 由实例化到销毁的过程。在详细讨论 bean 生命周期前,先上一张图,后面也会围绕这张图展开讨论。java
图1 bean实例化过程git
接下来对照上图,一步一步对 singleton 类型 bean 的生命周期进行解析:github
上述流程从宏观上对 Spring 中 singleton 类型 bean 的生命周期进行了描述,接下来讲说所上面流程中的一些细节问题。
先看流程中的第二步 -- 设置对象属性。在这一步中,对于普通类型的属性,例如 String,Integer等,比较容易处理,直接设置便可。可是若是某个 bean 对象依赖另外一个 bean 对象,此时就不能直接设置了。Spring 容器首先要先去实例化 bean 依赖的对象,实例化好后才能设置到当前 bean 中。大体流程以下:spring
图2 依赖实例化流程图数组
上面图片描述的依赖比较简单,就是 BeanA 依赖 BeanB。如今考虑这样一种状况,BeanA 依赖 BeanB,BeanB 依赖 BeanC,BeanC 又依赖 BeanA。三者造成了循环依赖,以下所示:框架
图3 循环依赖post
对于这样的循环依赖,根据依赖注入方式的不一样,Spring 处理方式也不一样。若是依赖靠构造器方式注入,则没法处理,Spring 直接会报循环依赖异常。这个理解起来也不复杂,构造 BeanA 时须要 BeanB 做为构造器参数,此时 Spring 容器会先实例化 BeanB。构造 BeanB 时,BeanB 又须要 BeanC 做为构造器参数,Spring 容器又不得不先去构造 BeanC。最后构造 BeanC 时,BeanC 又依赖 BeanA 才能完成构造。此时,BeanA 还没构造完成,BeanA 要等 BeanB 实例化好才能完成构造,BeanB 又要等 BeanC,BeanC 等 BeanA。这样就造成了死循环,因此对于以构造器注入方式的循环依赖是无解的,Spring 容器会直接报异常。对于 setter 类型注入的循环依赖则能够顺利完成实例化并依次注入,这里具体细节就不说了,详细能够参考《Spring源码深度解析》一书相关章节。spa
循环依赖问题说完,接下来 bean 实例化流程中的第6步 -- 调用 BeanPostProcessor 后置处理方法。先介绍一下 BeanPostProcessor 接口,BeanPostProcessor 接口中包含了两个方法,其定义以下:代理
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception; Object postProcessAfterInitialization(Object bean, String beanName) throws Exception; }
BeanPostProcessor 是一个颇有用的接口,经过实现接口咱们就能够插手 bean 的实例化过程,为拓展提供了可能。咱们所熟知的 AOP 就是在这里进行织如入,具体点说是在 postProcessAfterInitialization(Object bean, String beanName) 执行织入逻辑的。下面就来讲说 Spring AOP 织入的流程,以及 AOP 是怎样和 IOC 整合的。先说 Spring AOP 织入流程,大体以下:code
你们如今应该知道 AOP 是怎样做用在 bean 上的了,那么 AOP 是怎样和 IOC 整合起来并协同工做的呢?下面就来简单说一下。
Spring AOP 生成代理类的逻辑是在 AbstractAutoProxyCreator 相关子类中实现的,好比 DefaultAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator 等。上面说了 BeanPostProcessor 为拓展留下了可能,这里 AbstractAutoProxyCreator 就将可能变为了现实。AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口,这样 AbstractAutoProxyCreator 能够在 bean 初始化时作一些事情。光继承这个接口还不够,继承这个接口只能获取 bean,要想让 AOP 生效,还须要拿到切面对象(包含 Pointcut 和 Advice)才行。因此 AbstractAutoProxyCreator 同时继承了 BeanFactoryAware 接口,经过实现该接口,AbstractAutoProxyCreator 子类就可拿到 BeanFactory,有了 BeanFactory,就能够获取 BeanFactory 中全部的切面对象了。有了目标对象 bean,全部的切面类,此时就能够为 bean 生成代理对象了。
图4 AbstractAutoProxyCreator继承图(删掉了一些不关心的继承分支)
到这里,从宏观上已经对 bean 的生命流程进行了较为详细的描述。因为暂时能力有限,只能从宏观上分析,之前尝试过去看 Spring IOC 的实现代码,感受仍是太复杂了,细节太多,跟踪了十几二十个方法后就开始凌乱了。在几回失败的尝试后,终于放弃了。后来总结了一下失败的缘由,当时本身刚工做不是好久,代码写的少,经验不足。而且在对 Spring 不少特性不熟悉的状况下就去看 Spring 源码,结果只能处处碰壁,陷入 Spring 各类细节之中久久不能自拔?。因此对于想看某个框架代码的同窗,必定要在熟练使用这个框架的基础上再去看。不要像我这样急于求成,否则到最后只能失败啊。本人这篇博客创建在仿写了 Spring IOC 和 AOP的基础上写出来的,在仿写过程当中参考了黄亿华前辈的 tiny-spring 项目,有兴趣的同窗能够读读 tiny-spring。我本身仿写的项目也放在了github上,传送门 --> toy-spring。
本篇博客到此结束,若是有写错的地方,欢迎指出来,谢谢!若是错误的地方对你形成了困扰,我表示很抱歉。
参考 :
本文在知识共享许可协议 4.0 下发布,转载请注明出处
做者:coolblog
为了得到更好的分类阅读体验,
请移步至本人的我的博客: http://www.coolblog.xyz
本做品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。