The Spring framework, by default, loads and eagerly initializes all beans at the application startup itself. In our application, we might have some pretty resource-intensive beans. We’ll prefer to load such beans on a need basis. We can achieve this using the Spring @Lazy annotation.
In this tutorial, we’ll learn how to use @Lazy annotation to lazily load our beans.
If we mark our Spring configuration class with @Lazy annotation, then all defined beans with @Bean annotation will get lazily loaded:
@Configuration @ComponentScan(basePackages = "com.programmergirl.university") @Lazy public class AppConfig { @Bean public Student student() { return new Student(); } @Bean public Teacher teacher() { return new Teacher(); } }
@Bean @Lazy public Teacher teacher() { return new Teacher(); }
Let’s quickly test out this functionality by running our application:
public class SampleApp { private static final Logger LOG = Logger.getLogger(SampleApp.class); public static void main(String args[]) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); LOG.info("Application Context is already up"); // Beans in our Config class lazily loaded Teacher teacherLazilyLoaded = context.getBean(Teacher.class); Student studentLazilyLoaded = context.getBean(Student.class); } }
Bean factory for ...AnnotationConfigApplicationContext: ...DefaultListableBeanFactory: [...] ... Application Context is already up Inside Teacher Constructor Inside Student Constructor
We can also use @Lazy annotation at an injection point: constructor, setter or field-level.
Let’s say we have a Classroom class that we want to lazy-load:
@Component @Lazy public class Classroom { public Classroom() { System.out.println("Inside Classroom Constructor"); } ... }
@Component public class University { @Lazy @Autowired private Classroom classroom; public University() { System.out.println("Inside University Constructor"); } public void useClassroomBean() { this.classroom.getDetails(); ... } }
// in our main() method AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); LOG.info("Application Context is already up"); University university = context.getBean(University.class); LOG.info("Time to use the actual classroom bean..."); university.useClassroomBean();
Bean factory for ...AnnotationConfigApplicationContext: ...DefaultListableBeanFactory: [...] ... Inside University Constructor ... Application Context is already up Time to use the actual classroom bean... Inside Classroom Constructor
Please note that, for lazy-injection, we must use @Lazy annotation on both the component class as well as the injection point.
In this quick tutorial, we learned how to lazy load our Spring beans. We talked about lazy initialization and lazy injection.