lazy-init 延迟加载应用
ApplicationContext 容器的默认值行为是在启动服务器时将所有Singleton Bean 提前进行实例,提前实例化意味着作为初始化过程的一部分,ApplicationContext 实例会创建并配置所有的singleton Bean.
例如:
<bean id="testBean" class="cn.lagou.LazyBean" />
该bean默认的设置为:
<bean id="testBean" calss="cn.lagou.LazyBean" lazy-init="false" />
lazy-init=“false” ,立即加载,表示在spring 启动时,立刻进行实例化,
如果不想让一个singleton bean在ApplicationContext实现初始化时被提前实例化,那么可以将bean设置为延迟实例化.
<bean id="testBean" calss="cn.lagou.LazyBean" lazy-init="true" />
设置lazy-init 为true的bean 将不会在ApplicationContext 启动时提前被实例化,而是第一次向容器通过getBean 索取bean时实例化的.
如果一个设置了立即加载的bean1 ,引用了一个延迟加载的bean2,那么bean1 在容器启动时被实例化,而bean2 由于被bean1 引用,所以也被实例化,这种情况也符合延迟加载的bean在第一次调用时才被实例化的规则.
也可以在容器层次中通过元素上使用"default-lazy-int"属性来控制延时初始化,配置如下:
如果一个bean的scope属性为scope="pototype"时,即使设置了lazy-init=“false” ,容器启动时也不会实例化bean,而是调用 getBean 方法实例化的.
应用场景:
(1) 开启延迟加载一定程度提高容器启动和运转性能.
(2) 对于不常用的Bean 设置延迟加载,这样偶尔使用的时候再加载,不必要从一开始该bean 就占用资源.
lazy-init 延迟加载机制分析
普通Bean的初始化是在容器启动初始化阶段执行的,而被lazy-init=true 修饰的bean则是在从容器里第一次进行context.getBean()时进行触发.Spring启动的时候会把所有bean信息解析转化成Spring 能够识别的BeanDefinition 并存到Hashmap 中供后续的初始化时用,然后对每个BeanDefinition 进行处理,如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进行初始化并依赖注入.
总结
对于被修饰为lazy-init的bean,Spring 容器初始化阶段不会进行init 并且依赖注入,当第一次进行getBean的时候,才会进行初始化并依赖注入. 对于非延迟加载的bean,getBean的时候会从缓存中获取,因为容器初始化阶段Bean已经初始化完并缓存起来了.