深入理解 Spring 的 Lazy Loading:原理、实现与应用场景

devtools/2025/1/23 22:04:34/

延迟加载(Lazy Loading)是 Spring 容器管理 Bean 的一种策略,指 只有在需要时(调用 getBean() 方法获取 Bean 时)才会实例化该 Bean。这是 Spring 提供的一种优化机制,用于提高启动效率和降低资源占用。


1. 延迟加载的含义

  • 在延迟加载模式下,Spring 容器初始化时不会立即实例化所有 Bean,而是等到真正需要使用时(即调用 getBean() 方法时),才创建 Bean 实例。
  • 如果不启用延迟加载(非 Lazy 模式),则所有单例(singleton) Bean 会在容器启动时立即实例化。

2. 延迟加载的优点

  1. 节省资源:

    • 容器启动时不需要加载和创建所有 Bean,启动速度更快。
    • 避免不必要的对象实例化,降低内存占用,尤其是对于未使用的 Bean。
  2. 适合轻量级应用:

    • 在资源有限的环境中(如嵌入式系统),延迟加载可以显著优化性能。
    • 在开发或测试阶段,也可以通过延迟加载缩短启动时间。
  3. 按需加载:

    • 只有在确实需要使用某个 Bean 时,才会创建它的实例,避免初始化不必要的逻辑。

3. 延迟加载的实现方式

(1) 使用 @Lazy 注解

在类或方法上添加 @Lazy 注解,可以让单例 Bean 延迟加载。

示例代码:

@Component
@Lazy // 延迟加载
public class ExpensiveBean {public ExpensiveBean() {System.out.println("ExpensiveBean created!");}
}

测试代码:

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println("Container initialized.");
ExpensiveBean bean = context.getBean(ExpensiveBean.class); // 此时 Bean 才会创建

运行结果:

Container initialized.
ExpensiveBean created!

解释:

  • @Lazy 生效后,ExpensiveBean 不会在容器启动时被创建。
  • 只有在调用 getBean() 时,ExpensiveBean 才会被实例化。

(2) 如果未使用 @Lazy

代码:

@Configuration
public class AppConfig {@Beanpublic ExpensiveBean expensiveBean() {return new ExpensiveBean(); // 无 @Lazy,默认预加载}
}

运行结果:

ExpensiveBean created!
Container initialized.

解释:

  • 默认情况下,ApplicationContext 会在启动时实例化所有单例 Bean,所以在输出 "Container initialized." 前就会创建 ExpensiveBean

(3) XML 配置方式

在 XML 文件中为 Bean 配置延迟加载:

<bean id="expensiveBean" class="com.example.ExpensiveBean" lazy-init="true"/>

(4) 在 @Configuration 中使用

对于使用 Java 配置的项目,可以在配置类中的 @Bean 方法上添加 @Lazy

@Configuration
public class AppConfig {@Bean@Lazypublic ExpensiveBean expensiveBean() {return new ExpensiveBean();}
}

4. 延迟加载的默认行为

(1) BeanFactory 的默认行为
  • BeanFactory 是一个轻量级容器,默认使用延迟加载策略
  • 它不会在容器启动时实例化任何 Bean,而是等到调用 getBean() 方法时才实例化。
(2) ApplicationContext 的默认行为
  • ApplicationContext 是 Spring 容器的常用实现,默认会在启动时预加载所有单例(singleton) Bean
  • 例外情况:
    • 如果使用 @Lazy 注解或 XML 中的 lazy-init="true",单例 Bean 会延迟加载。
    • 非单例(prototype Scope)的 Bean 本身默认是延迟加载的。

5. 延迟加载与非延迟加载的对比

行为延迟加载非延迟加载
实例化时机调用 getBean() 时实例化容器启动时实例化
适用范围需要优化启动时间或资源消耗的场景高性能服务器或需要预加载依赖的场景
容器类型BeanFactory 默认延迟加载ApplicationContext 默认非延迟加载
预加载的 Bean无(除非显式调用)单例 Bean 默认全部实例化
性能表现启动速度快,可能会导致首次调用延迟启动时占用更多内存,运行时性能更高

6. 示例场景

  1. 资源密集型对象的加载:

    • 如果某个 Bean 的创建非常耗时(例如连接外部服务),使用延迟加载可以避免容器启动时的性能瓶颈。
  2. 开发与测试阶段:

    • 在开发和测试中,延迟加载可以缩短容器的启动时间,提升开发效率。
  3. 条件性加载:

    • 某些 Bean 只有在特定条件下才会被使用,延迟加载可以避免不必要的资源消耗。

7. 总结

  • 延迟加载的本质: Bean 只有在第一次使用时才会被实例化。
  • 优点: 减少容器启动时的资源消耗,适合轻量级或资源受限的场景。
  • 默认行为: BeanFactory 默认延迟加载,而 ApplicationContext 默认预加载单例 Bean。
  • 实现方式: 使用 @Lazy 注解或 XML 配置轻松启用延迟加载。

通过灵活地使用延迟加载,可以显著优化应用程序的启动时间和资源利用率,特别是在复杂项目或资源密集型应用中。


http://www.ppmy.cn/devtools/152973.html

相关文章

wireshark工具简介

目录 1 wireshark介绍 2 wireshark抓包流程 2.1 选择网卡 2.2 停止抓包 2.3 保存数据 3 wireshark过滤器设置 3.1 显示过滤器的设置 3.2 抓包过滤器 4 wireshark的封包列表与封包详情 4.1 封包列表 4.2 封包详情 参考文献 1 wireshark介绍 wireshark是非常流行的网络…

HTTPS的加密原理

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是一个安全的 HTTP 协议&#xff0c;结合了 SSL/TLS 协议来提供数据加密、身份验证和数据完整性保护。其核心加密原理可以分为以下几个步骤&#xff1a; 对称加密和非对称加密 HTTPS 使用了对称加密和非对称…

Java学习,List移动元素

Java实现List中元素的循环移动&#xff08;即将列表中的元素向右或向左移动指定数量的位置&#xff09;&#xff0c;可以使用多种方法。 List元素移动指定位置&#xff1a; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class…

Ardupilot开源无人机之Geek SDK进展2024-2025

Ardupilot开源无人机之Geek SDK进展2024-2025 1. 源由2. 状态3. TODO3.1 【进行中】跟踪目标框3.2 【暂停】onnxruntime版本3.3 【完成】CUDA 11.8版本3.4 【完成】pytorch v2.5.1版本 - Jetpack53.5 【未开始】Inference性能3.6 【未开始】特定目标集Training 4. Extra-Work4.…

Django学习笔记(启动项目)-03

Django学习笔记(启动项目)-03 1、在urls文件中配置一个路由url 2、在views文件中创建视图函数 3、启动项目测试结果 # 输入项目启动命令 python manage.py runserver4、创建HTML模版和静态文件 1、在templates文件夹中创建一个html 2、创建url路由与视图函数 3、测试效果 4、…

(三)线性代数之二阶和三阶行列式详解

在前端开发中&#xff0c;尤其是在WebGL、图形渲染、或是与地图、模型计算相关的应用场景里&#xff0c;行列式的概念常常在计算变换矩阵、进行坐标变换或进行图形学算法时被使用。理解二阶和三阶行列式对于理解矩阵运算、旋转、平移等操作至关重要。下面&#xff0c;我将结合具…

docker Ubuntu实战

目录 Ubuntu系统环境说明 一、如何安装docker 二、发布.netcore应用到docker中 Ubuntu系统环境说明 cat /etc/os-release PRETTY_NAME"Ubuntu 22.04.5 LTS" NAME"Ubuntu" VERSION_ID"22.04" VERSION"22.04.5 LTS (Jammy Jellyfish)&quo…

如何优化虚拟化服务器在高负载环境下的性能?

虚拟化服务器利用虚拟化技术将物理服务器的硬件资源如CPU、内存、硬盘和网络带宽等)划分成多个虚拟机&#xff0c;每个虚拟机像独立的物理服务器一样运行操作系统和应用程序。虚拟机之间相互隔离&#xff0c;彼此共享底层硬件资源。虚拟化服务器可以通过Hypervisor虚拟机监控器…