1. 概述
默认情况下,Spring 会在应用上下文启动时立即创建所有单例 bean。 这么做的原因很简单:在启动时就发现并解决所有潜在问题,而不是等到运行时才报错。
但有些场景下,我们希望 bean 不是在应用上下文启动时创建,而是在首次请求时才创建。
这篇快速指南将深入探讨 Spring 的 @Lazy 注解。
2. 延迟初始化
@Lazy 注解自 Spring 3.0 版本就已存在。有几种方式可以告诉 IoC 容器延迟初始化 bean。
2.1. 在 @Configuration 类上使用
当我们在 @Configuration 类上添加 @Lazy 注解时,表示该类中所有带 @Bean 注解的方法都应该延迟加载。
这等价于 XML 配置中的 default-lazy-init="true"
属性。
看个例子:
@Lazy
@Configuration
@ComponentScan(basePackages = "com.baeldung.lazy")
public class AppConfig {
@Bean
public Region getRegion(){
return new Region();
}
@Bean
public Country getCountry(){
return new Country();
}
}
测试一下效果:
@Test
public void givenLazyAnnotation_whenConfigClass_thenLazyAll() {
AnnotationConfigApplicationContext ctx
= new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
ctx.getBean(Region.class);
ctx.getBean(Country.class);
}
可以看到,所有 bean 都在首次请求时才创建:
Bean factory for ...AnnotationConfigApplicationContext:
...DefaultListableBeanFactory: [...];
// application context started
Region bean initialized
Country bean initialized
如果只想对特定 bean 应用延迟加载,移除类上的 @Lazy,然后在目标 bean 的配置上添加:
@Bean
@Lazy(true)
public Region getRegion(){
return new Region();
}
2.2. 配合 @Autowired 使用
继续前,建议先了解 @Autowired 和 @Component 注解的基础知识。
这里的关键是通过另一个 bean 来引用延迟初始化的 bean。
要延迟加载的 bean:
@Lazy
@Component
public class City {
public City() {
System.out.println("City bean initialized");
}
}
引用它的 bean:
public class Region {
@Lazy
@Autowired
private City city;
public Region() {
System.out.println("Region bean initialized");
}
public City getCityInstance() {
return city;
}
}
注意:两处都需要添加 @Lazy 注解。
在 City 类上使用 @Component 注解,并通过 @Autowired 引用:
@Test
public void givenLazyAnnotation_whenAutowire_thenLazyBean() {
// 加载应用上下文
Region region = ctx.getBean(Region.class);
region.getCityInstance();
}
这里 City bean 只有在调用 getCityInstance() 方法时才会初始化。
3. 总结
这篇快速指南中,我们学习了 Spring @Lazy 注解的基础知识,并探讨了多种配置和使用方式。
✅ 关键要点:
- 延迟初始化能优化启动速度,但可能掩盖配置问题
- 类级别注解影响所有 bean,方法级别只针对特定 bean
- 配合 @Autowired 使用时,两处都需要 @Lazy
⚠️ 踩坑提醒:
- 延迟加载的 bean 如果存在循环依赖,会在首次使用时才暴露问题
- 启动时无法发现的错误会推迟到运行时
完整代码示例可在 GitHub 获取。