延迟加载
Spring在启动时,默认是将所有的singleton bean提前实例化,如果设置了lazy-init=”ture”的话,就可以设置这个bean在ApplicationContext启动服务器时不被实例化,在调用他的getBean索取bean时进行实例化,实现延迟加载。这么设置的目的是对不常用的bean设置延迟加载,避免一开始启动服务器占用资源。
延迟加载原理
通过源码分析,在bean创建过程中中间环节有一个非抽象,非单例,非延迟加载的判断。如果是延迟加载就直接不处理,就不会完成该bean的创建。
循环依赖问题
循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如A依赖于B,B依赖于C,C⼜依赖于A。注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。
场景:
构造器的循环依赖(构造器注⼊)
Field 属性的循环依赖(set注⼊)
其中,构造器的循环依赖问题⽆法解决,因为构造函数里面必须要有东西,但是根本没法完成A的实例化放入缓存中,只能拋出 BeanCurrentlyInCreationException 异常。在解决属性循环依赖时,spring采⽤的是提前暴露对象的⽅法。
Spring如何解决
假设Bean A 和Bean B 互相依赖,产生了循环依赖问题,那么Spring在Bean A在实例化后会将它放入三级缓存中,并且扩展后放入二级缓存。接着B创建的时候,会发现他依赖A,然后依次从一级缓存,二级缓存,三级缓存中查找实例化的依赖对象,找到后就拿来完成Bean B的装配并放入一级缓存中,接着删除二级缓存,三级缓存中的对象,而Bean A此时还没创建完成,就会直接从一级缓存中拿到Bean B来使用,解决了循环依赖问题。