初始化(Lazy Initialization)是一种在需要时才创建或初始化对象的策略。它的目的是推迟对象的创建或初始化,直到第一次使用该对象的时候。
延迟初始化可以带来以下几个好处:
节省资源:延迟初始化可以避免在应用程序启动时创建或初始化大量的对象,从而节省内存和处理器资源。
提高性能:延迟初始化可以减少应用程序启动时间,因为只有在需要时才会创建或初始化对象。
避免不必要的开销:延迟初始化可以避免创建或初始化不会被使用的对象,从而减少不必要的开销。
注意:延迟初始化可能会引入一些潜在的问题,例如线程安全性、内存泄漏等。因此,在实现延迟初始化时,需要注意处理这些潜在的问题,并确保在需要时正确地创建或初始化对象。
默认情况下,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()