外观
介绍一下类的懒加载
⭐ 题目日期:
小红书 - 2024/11/11
📝 题解:
类的懒加载(Lazy Loading)详解
懒加载(Lazy Loading)是一种延迟初始化技术,其核心思想是 在需要时才创建或加载资源,避免不必要的性能开销。以下是懒加载在不同场景下的实现方式、优缺点及实际应用示例:
1. 懒加载的核心思想
- 延迟初始化:对象的创建或数据的加载推迟到首次访问时。
- 资源优化:减少启动时间和内存占用,提升性能。
- 按需加载:适用于初始化成本高或使用频率低的资源。
2. 不同上下文中的懒加载实现
(1) Spring 框架中的 Bean 懒加载
- 实现方式: 使用
@Lazy
注解标记 Bean,Spring 容器在启动时不会初始化该 Bean,而是等到首次注入或获取时再初始化。
@Configuration
public class AppConfig {
@Bean
@Lazy // 懒加载
public ExpensiveService expensiveService() {
return new ExpensiveService();
}
}
- 适用场景:
- Bean 初始化耗时(如数据库连接、第三方服务初始化)。
- Bean 可能不会被立即使用(如功能模块按需加载)。
(2) Hibernate ORM中的关联懒加载
- 实现方式: 在实体关联字段(如
@OneToMany
)上设置fetch = FetchType.LAZY
,延迟加载关联数据。
@Entity
public class Order {
@OneToMany(fetch = FetchType.LAZY)
private List<OrderItem> items; // 懒加载关联的订单项
}
- 注意事项:
- 访问懒加载字段需在 Hibernate Session 未关闭的情况下进行,否则会抛出
LazyInitializationException
。 - 可通过
Fetch Join
或Hibernate.initialize()
主动加载。
- 访问懒加载字段需在 Hibernate Session 未关闭的情况下进行,否则会抛出
(3) 单例模式的懒加载(线程安全)
- 实现方式: 使用双重检查锁定(Double-Checked Locking)或静态内部类。
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
(4) Java 8 的 Supplier 延迟初始化
- 实现方式: 利用
Supplier
接口延迟创建对象。
public class Lazy<T> {
private Supplier<T> supplier;
private T value;
public Lazy(Supplier<T> supplier) {
this.supplier = supplier;
}
public T get() {
if (value == null) {
value = supplier.get();
}
return value;
}
}
// 使用示例
Lazy<ExpensiveResource> resource = new Lazy<>(ExpensiveResource::new);
3. 懒加载的优缺点
4. 适用场景
- 高开销对象:如数据库连接池、缓存初始化。
- 低频使用资源:如日志服务、辅助工具类。
- 模块化架构:按需加载插件或功能模块。
- 大规模数据:如分页查询、懒加载列表数据。
5. 注意事项
- 线程安全:多线程环境下需确保懒加载代码的原子性。
- 异常处理:捕获初始化时的异常,避免程序崩溃。
- 资源释放:懒加载的资源需在适当时候释放(如 Spring Bean 的销毁回调)。
- 循环依赖:在依赖注入框架中,懒加载可能掩盖循环依赖问题。
6. 示例:Spring 中的懒加载实战
配置类
@Configuration
public class LazyConfig {
@Bean
@Lazy
public HeavyResource heavyResource() {
System.out.println("Initializing HeavyResource...");
return new HeavyResource();
}
}
使用类
@Service
public class MyService {
@Autowired
private HeavyResource heavyResource; // 首次访问时初始化
public void doWork() {
heavyResource.process(); // 此时才会创建 HeavyResource 实例
}
}
输出结果
// 启动时无输出
// 调用 doWork() 后输出:Initializing HeavyResource...
总结
懒加载通过延迟资源初始化,优化了应用的启动性能和内存使用,尤其在处理高开销、低频访问的资源时效果显著。然而,需权衡其带来的运行时延迟和复杂度增加。在 Spring、Hibernate 等框架中,合理利用懒加载机制能显著提升系统效率。