1. Overview
By default, Spring creates all singleton beans eagerly at the startup/bootstrapping of the application context. The reason behind this is simple: to avoid and detect all possible errors immediately rather than at runtime.
However, there’re cases when we need to create a bean, not at the application context startup, but when we request it.
In this quick tutorial, we’re going to discuss Spring’s @Lazy annotation.
2. Lazy Initialization
The @Lazy annotation has been present since Spring version 3.0. There’re several ways to tell the IoC container to initialize a bean lazily.
2.1. @Configuration Class
When we put @Lazy annotation over the @Configuration class, it indicates that all the methods with @Bean annotation should be loaded lazily.
This is the equivalent for the XML based configuration’s default-lazy-init=“true“ attribute.
Let’s have a look here:
@Lazy
@Configuration
@ComponentScan(basePackages = "com.baeldung.lazy")
public class AppConfig {
@Bean
public Region getRegion(){
return new Region();
}
@Bean
public Country getCountry(){
return new Country();
}
}
Let’s now test the functionality:
@Test
public void givenLazyAnnotation_whenConfigClass_thenLazyAll() {
AnnotationConfigApplicationContext ctx
= new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
ctx.getBean(Region.class);
ctx.getBean(Country.class);
}
As we see, all beans are created only when we request them for the first time:
Bean factory for ...AnnotationConfigApplicationContext:
...DefaultListableBeanFactory: [...];
// application context started
Region bean initialized
Country bean initialized
To apply this to only a specific bean, let’s remove the @Lazy from a class.
Then we add it to the config of the desired bean:
@Bean
@Lazy(true)
public Region getRegion(){
return new Region();
}
2.2. With @Autowired
Before going ahead, check out these guides for @Autowired and @Component annotations.
Here, in order to initialize a lazy bean, we reference it from another one.
The bean that we want to load lazily:
@Lazy
@Component
public class City {
public City() {
System.out.println("City bean initialized");
}
}
And it’s reference:
public class Region {
@Lazy
@Autowired
private City city;
public Region() {
System.out.println("Region bean initialized");
}
public City getCityInstance() {
return city;
}
}
Note, that the @Lazy is mandatory in both places.
With the @Component annotation on the City class and while referencing it with @Autowired:
@Test
public void givenLazyAnnotation_whenAutowire_thenLazyBean() {
// load up ctx appication context
Region region = ctx.getBean(Region.class);
region.getCityInstance();
}
Here, the City bean is initialized only when we call the getCityInstance() method.
3. Conclusion
In this quick tutorial, we learned the basics of Spring’s @Lazy annotation. We examined several ways to configure and use it.
As usual, the complete code for this guide is available on GitHub.