Spring 延迟初始化 Bean

什么是延迟初始化?

初始化(Lazy Initialization)是一种在需要时才创建或初始化对象的策略。它的目的是推迟对象的创建或初始化,直到第一次使用该对象的时候。

延迟初始化可以带来以下几个好处:

  • 节省资源:延迟初始化可以避免在应用程序启动时创建或初始化大量的对象,从而节省内存和处理器资源。

  • 提高性能:延迟初始化可以减少应用程序启动时间,因为只有在需要时才会创建或初始化对象。

  • 避免不必要的开销:延迟初始化可以避免创建或初始化不会被使用的对象,从而减少不必要的开销。

注意:延迟初始化可能会引入一些潜在的问题,例如线程安全性、内存泄漏等。因此,在实现延迟初始化时,需要注意处理这些潜在的问题,并确保在需要时正确地创建或初始化对象。

Spring Bean 延迟初始化

默认情况下,ApplicationContext 实现会在初始化过程中急切地创建和配置所有单例 bean。通常,这种预实例化是可取的,因为配置或运行环境中的错误会立即被发现,而不是几小时甚至几天后。当不需要立即初始化 bean 时,可以通过将 bean 定义标记为延迟(Lazy)初始化来防止单例 bean 的预实例化。延迟初始化的 bean 告诉 IoC 容器在第一次请求时创建 bean 实例,而不是在应用启动时(即用时才创建,不用不创建的思想)。

在 XML 数据配置文件中,Bean 的延迟初始化由 <bean/> 元素上的 lazy-init 属性进行控制,如下例所示:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

当 ApplicationContext 使用上面配置时,ApplicationContext 启动时不会急切地预实例化 “lazy” Bean,而 “not.lazy” Bean 则会急切地预实例化。

但是,当一个延迟始化的 Bean 是一个未延迟初始化的单例 Bean 的依赖关系时,ApplicationContext 会在启动时创建延迟初始化的 Bean,因为它必须满足单例的依赖关系。延迟初始化的 Bean 被注入到其他未延迟初始化的单例 Bean 中。

您还可以通过使用 <beans/> 元素上的 default-lazy-init 属性在容器级别控制懒初始化,如下例所示:

<beans default-lazy-init="true">
   <!-- 没有 bean 将被预先初始化... -->
</beans>

延迟初始化示例

该示例将创建三个 Bean,分别是 beanOne、beanTwo、beanThree,其中 beanOne 和 beanTwo 均是延迟初始化 Bean;beanThree 是非延迟初始化 Bean,并且依赖了 beanOne 延迟初始化的 Bean,代码如下:

applicationContext-ioc-demo4.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!-- 定义 beanOne 和 beanTwo 均为延迟初始化 Bean -->
   <bean id="beanOne" class="com.hxstrive.spring5.ioc.demo4.BeanOne" lazy-init="true" />
   <bean id="beanTwo" class="com.hxstrive.spring5.ioc.demo4.BeanTwo" lazy-init="true" />

   <!-- beanThree 为非延迟初始化 Bean,并且依赖 beanOne -->
   <bean id="beanThree" class="com.hxstrive.spring5.ioc.demo4.BeanThree">
       <property name="beanOne" ref="beanOne" />
   </bean>

</beans>

BeanOne.java:

package com.hxstrive.spring5.ioc.demo4;

public class BeanOne {

   public BeanOne() {
       System.out.println("BeanOne()");
   }

}

BeanTwo.java:

package com.hxstrive.spring5.ioc.demo4;

public class BeanTwo {

   public BeanTwo() {
       System.out.println("BeanTwo()");
   }
}

BeanThree.java:

package com.hxstrive.spring5.ioc.demo4;

public class BeanThree {
   private BeanOne beanOne;

   public BeanThree() {
       System.out.println("BeanThree()");
   }

   public BeanOne getBeanOne() {
       return beanOne;
   }

   public void setBeanOne(BeanOne beanOne) {
       this.beanOne = beanOne;
   }
}

Main.java:

package com.hxstrive.spring5.ioc.demo4;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* Bean 延迟初始化
* @author hxstrive.com
*/
public class Main {

   public static void main(String[] args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-ioc-demo4.xml");
       context.getBean(BeanThree.class);
   }

}

运行示例,输出如下:

BeanThree()
BeanOne()
说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号