Spring框架懒加载怎么实现?

Spring 懒加载实现全解析:让你的应用启动快人一步

在实际项目开发中,我们可能遇到这样的场景:应用启动时,Spring 容器会迫不及待地创建所有单例 Bean,即使有些 Bean 在很长一段时间内都用不到。这不仅拖慢了启动速度,还占用了宝贵的内存。Spring 的"懒加载"(Lazy Initialization)正是为了解决这个问题而生。今天这篇博客,带你从概念到实现,再到原理,彻底玩转 Spring 懒加载。


一、什么是懒加载?

懒加载 是一种设计思想:等到真正需要某个资源的时候,才去创建或加载它

在 Spring 容器中,默认的行为是 迫切加载 (Eager Initialization)------ 所有单例 Bean 会在容器启动阶段完成实例化与依赖注入。而开启懒加载后,单例 Bean 的创建时机被推迟到第一次被请求时(如 getBean() 或依赖注入到另一个 Bean)。

下面这张图直观对比了两种策略的区别:

二、如何开启 Spring 懒加载?

Spring 提供了非常灵活的配置方式,可以用注解,也可以用 XML,还能做全局开关。

1. 使用 @Lazy 注解

最直接的方式,在需要懒加载的 Bean 上标注 @Lazy

java 复制代码
@Component
@Lazy
public class EmailService {
    public EmailService() {
        System.out.println("EmailService 被创建了!");
    }

    public void send(String message) {
        System.out.println("发送邮件:" + message);
    }
}

在配置类里搭配 @Bean 使用:

java 复制代码
@Configuration
public class AppConfig {
    @Bean
    @Lazy
    public EmailService emailService() {
        return new EmailService();
    }
}

此时,Spring 容器启动时并不会创建 EmailService,直到有人调用 context.getBean(EmailService.class) 或它被注入到其他 Bean 并被使用时才会实例化。

懒加载也能用在注入点 :如果某个 Bean 本身不是懒加载,但想让它依赖的 Bean 延迟初始化,可以在注入点加 @Lazy

java 复制代码
@Component
public class NotificationManager {
    @Autowired
    @Lazy
    private EmailService emailService;

    public void notifyUser() {
        emailService.send("欢迎注册"); // 此时才创建 EmailService
    }
}

2. 通过 XML 配置懒加载

在传统 XML 配置中,可以给 <bean> 标签添加 lazy-init="true" 属性。

xml 复制代码
<bean id="emailService" class="com.example.EmailService" lazy-init="true" />

如果想全局默认懒加载,在 <beans> 根元素加上 default-lazy-init="true"

xml 复制代码
<beans default-lazy-init="true">
    <bean id="emailService" class="com.example.EmailService" />
    <bean id="smsService" class="com.example.SmsService" />
</beans>

但要注意,如果某个 Bean 显式设置了 lazy-init="false",则以自身设置为准。

3. Spring Boot 全局开关

在 Spring Boot 应用中,可以在 application.properties 里添加一行配置:

properties 复制代码
spring.main.lazy-initialization=true

这会让所有 Bean 都默认懒加载。如果有些 Bean 必须立即初始化,可以单独加上 @Lazy(false) 覆盖全局设置。


三、懒加载的内部原理

知其然,也要知其所以然。Spring 是如何实现懒加载的?核心围绕 BeanFactory 的创建流程。

Spring 在读取 BeanDefinition 时,会检查 lazyInit 属性。若为 true,则在容器刷新阶段的 finishBeanFactoryInitialization() 中跳过该 Bean 的实例化。真正触发创建的地方,是 AbstractBeanFactorygetBean() 方法,其中调用了 getSingleton(),若缓存中不存在,则会走 createBean() 流程,并最终放入单例缓存。

小陷阱:懒 Bean 被非懒 Bean 依赖

如果一个懒加载的 Bean 被另一个非懒加载的 Bean 注入了,那么懒加载会失效,因为它会在容器启动时作为依赖被提前实例化。这是 Spring 依赖解析的必然结果,使用时务必注意。


四、懒加载实战演示

假设我们有如下三个组件:

  • OrderService:急切加载
  • EmailService:懒加载
  • SmsService:急切加载,但依赖 EmailService
java 复制代码
@Component
public class OrderService {
    public OrderService() {
        System.out.println("OrderService 实例化");
    }
}

@Component
@Lazy
public class EmailService {
    public EmailService() {
        System.out.println("EmailService 实例化");
    }
}

@Component
public class SmsService {
    @Autowired
    private EmailService emailService;

    public SmsService() {
        System.out.println("SmsService 实例化");
    }
}

启动容器,你会看到控制台输出:

复制代码
OrderService 实例化
EmailService 实例化
SmsService 实例化

咦?EmailService 明明是懒加载,为什么被创建了?因为 SmsService 是迫切加载,它又依赖了 EmailService,为了完成依赖注入,容器只好提前实例化 EmailService
解决办法 :在 SmsService 的注入点上也加 @Lazy,这样注入的是懒代理,不会立刻触发 EmailService 的实例化。

java 复制代码
@Autowired
@Lazy
private EmailService emailService;

这样再运行,控制台输出:

复制代码
OrderService 实例化
SmsService 实例化

EmailService 没有被创建,直到 SmsService 中真正调用 emailService.send(...) 时才会初始化。


五、何时该用懒加载?优缺点一览

优点

  • 加快启动速度:减少初始化时间,尤其适合微服务、Serverless 等对冷启动敏感的场景。
  • 节省内存:不立即使用的 Bean 不占用资源。
  • 按需加载:大型应用中,部分模块可能从不被访问,懒加载避免无用开销。

缺点

  • 隐藏错误:配置错误或依赖缺失在启动时不会被发现,延迟到运行时才暴露,增加排查难度。
  • 首次调用延迟:第一次请求时会触发 Bean 创建,可能带来较高的响应延迟(冷启动 spike)。
  • 复杂性:需要小心处理依赖关系,避免意外的迫切初始化。

推荐实践

  • 开发环境可全局关闭懒加载,尽早暴露配置问题。
  • 生产环境可根据需要开启全局懒加载,并用 @Lazy(false) 将核心 Bean(如数据库连接池、监控端点)标记为迫切加载。
  • 微服务架构下,Spring Boot 全局懒加载是一个常见优化手段。

六、总结

Spring 的懒加载通过 @Lazy 注解、XML 属性或 Boot 全局配置即可轻松实现。它的核心原理是延迟 Bean 的创建时机,直到第一次被请求。虽然能显著提升启动速度,但也会带来错误延时暴露等问题,因此需要根据实际情况审慎选择。

掌握懒加载,是在大型应用与云原生架构下进行启动优化的必修课。希望这篇博客能帮你透彻理解并灵活运用这一特性。如果觉得有帮助,欢迎点赞收藏,也欢迎在评论区交流你的实践心得!

相关推荐
熊猫_豆豆7 小时前
麦克斯韦方程组(电磁效应Python展示)
开发语言·python·电磁感应·麦克斯韦方程组
SilentSamsara7 小时前
属性查找顺序:实例 → 类 → 父类的完整 MRO
开发语言·python·算法·青少年编程
甄心爱学习7 小时前
【项目实训】法律文书智能摘要系统6
python·个人开发
yychen_java8 小时前
IDEA × Qoder:告别“手写Spring”,进入AI协作开发新时代
人工智能·spring·intellij-idea
小白学大数据8 小时前
Scrapling:极简高效的 Python 智能爬虫框架
开发语言·爬虫·python·数据分析
辣椒思密达8 小时前
Python爬虫中如何正确配置住宅IP代理?新手避坑指南
c语言·python
ZhiqianXia8 小时前
流畅的Python笔记
笔记·python
未若君雅裁8 小时前
Spring Bean 作用域、线程安全与生命周期
java·安全·spring
财经资讯数据_灵砚智能8 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年5月20日
人工智能·python·信息可视化·自然语言处理·ai编程·灵砚智能