@Lazy 通过延迟非核心 Bean 初始化加速容器启动,适用于远程客户端、缓存预热、消息监听器等重初始化组件;支持类、@Bean 方法、注入点三处声明,延迟后仍为线程安全单例。

直接跳过不急需的 Bean 初始化,让容器启动时只做最必要的事,是 @Lazy 提速的核心逻辑。
哪些 Bean 加了 @Lazy 最见效
不是所有 Bean 都值得延迟。真正拖慢启动的,通常是那些“一上来就干重活”的组件:
- 远程客户端:比如支付网关、短信服务、第三方 SDK,初始化常含网络连接、认证、心跳检测
- 缓存预热类:启动时全量加载数据库配置、商品分类、权限菜单等,耗时动辄几百毫秒到几秒
- 消息监听器:如 @KafkaListener 或 @RabbitListener 所在的消费者 Bean,实际业务未开始前完全无需激活
- 报表/导出服务:低频使用、构造复杂、依赖多个数据源或计算引擎
- 测试专用 Bean:配合 @Profile("test") 使用,开发环境可启用,生产自动跳过
@Lazy 的三种用法和对应效果
加在哪,决定谁被延迟、怎么延迟:
- 加在 @Service/@Component 类上:整个 Bean 延迟。注入它的地方拿到的是代理,首次调用方法才真正创建实例
- 加在 @Bean 方法上:仅该方法返回的 Bean 延迟。适合配置类中定义的中间件连接池(如 RedisConnectionFactory)、工具类实例
- 加在 @Autowired 字段或构造器参数上:不改变目标 Bean 自身行为,而是让当前类“按需获取”它。即使目标没加 @Lazy,也能触发懒加载代理
单例 Bean 延迟后还是单例吗
是的,且保证线程安全。Spring 内部用 ObjectFactory 封装创建逻辑,首次访问时执行一次 createBean,并将实例注册进 singletonObjects 缓存。后续所有请求都复用这个实例,只是“第一次来得晚一点”。
立即学习“Java免费学习笔记(深入)”;
全局开启与条件控制
如果项目里大部分非核心 Bean 都适合延迟,可以统一管控:
- 在 @Configuration 类上加 @ComponentScan(lazyInit = true),让指定包下所有组件默认延迟
- XML 配置中设 <beans default-lazy-init="true">
- 需要动态判断?支持 SpEL 表达式:@Lazy("#{environment['spring.profiles.active'] == 'dev'}")


















