By default, Spring ApplicationContext eagerly creates and initializes all ‘singleton scoped‘ beans during the application startup. In most cases, it helps detect the bean configuration issues at an early stage. But sometimes, we may need to mark some or all beans to be lazily initialized due to different project requirements.
1. @Lazy Initialization
Spring allows lazy beans creation in two ways:
- Applied to specific beans
- Configure the behavior globally
1.1. Only Specific Beans
To lazy load only specific beans, use @Lazy
annotation along with @Bean
annotation while declaring the bean.
@Configuration
public class AppConfig {
@Lazy
@Bean
public EmployeeManager employeeManager() {
return new EmployeeManagerImpl();
}
}
1.2. Global Configuration
To lazy load all beans, use @Lazy
annotation along with @Configuration
annotation at the class level.
@Lazy @Configuration public class AppConfig { @Bean public EmployeeManager employeeManager() { return new EmployeeManagerImpl(); } //other beans in this class are also lazy loaded }
The above configurations are equivalent to the XML-based configuration‘s default-lazy-init=“true” attribute.
<beans default-lazy-init="true">
<bean id="operations" class="com.howtodoinjava.spring.beans.Operations"></bean>
</beans>
2. Autowiring @Lazy Beans
Generally, beans are injected into other components using @Autowired annotation. In this case, we must use the @Lazy annotation at both places:
- The bean definition which we want to lazy load
- The place it is injected along with @Autowired annotation
@Lazy
@Service
public class EmployeeManagerImpl implements EmployeeManager {
//
}
@Controller
public class EmployeeController {
@Lazy
@Autowired
EmployeeManager employeeManager;
}
Without using
@Lazy
annotation at both places, autowiring will not work.
3. Demo
Let’s see the code of EmployeeManager, we are trying to lazy load.
//@Lazy -- Uncomment for lazy bean intializations
@Service
public class EmployeeManagerImpl implements EmployeeManager {
@Override
public Employee create() {
Employee emp = new Employee();
emp.setId(1);
emp.setName("Lokesh");
return emp;
}
@PostConstruct
public void onInit(){
System.out.println("EmployeeManagerImpl Bean is Created !!");
}
}
I have put the @PostConstruct
annotation to detect when the bean is created. Let us initialize the application context with:
3.1. Without Lazy Loading
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println("Bean Factory Initialized !!");
EmployeeManager empManager = ctx.getBean(EmployeeManager.class);
Employee emp = empManager.create();
Notice the program output. Here, the bean has been created and initialized before the bean factory is fully initialized.
EmployeeManagerImpl Bean is Created !!
Bean Factory Initialized !!
3.2. With Lazy Loading
Bean Factory Initialized !!
EmployeeManagerImpl Bean is Created !!
After enabling bean lazy loading, the bean factory is first fully initialized. Later when we requested the EmployeeManager bean, the factory then created the instance and returned it.
4. Conclusion
In this Spring tutorial, we learned about the basics of @Lazy annotation and how to use it for lazy bean initializations. we also saw an example of lazy loaded beans after the application context is fully initialized.
Drop me your questions in the comments section about the difference between lazy and eager loading in Spring.
Happy Learning !!