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 over on GitHub.