Lazy Initialization in Spring : Benefits and Trade-offs

Lazy Initialization in Spring : Benefits and Trade-offs

Introduction

Lazy initialization refers to delaying the creation and initialization of a Bean until it is requested for the first time, rather than at the application context start-up. Lazy initialization of beans which are rarely used can help manage resources and reduce application start-up time. However, eager initialization is the default behaviour in Spring and is the most recommended way to identify dependency injection and configuration errors at start-up time, rather than at run-time, as is the case with lazy initialization.

How to Lazy Initialize a Bean ?

To lazy initialize a Bean, you can use "@Lazy" annotation on any class which is annotated with "@Component" or any method annotated with "@Bean" .

Example : Eager Initialization

package com.example.dependencyinjection;
import org.springframework.stereotype.Component;

@Component
public class MyBusinessClass {
    //Certain other dependencies of MyBusinessClass 
    private final FirstDependency firstDepenedency;    
    private final SecondDependency secondDependency;

    public MyBusinessClass(FirstDependency firstDepenedency, SecondDependency secondDependency) {
        super();
        System.out.println("Initialization");
        this.firstDepenedency = firstDepenedency;
        this.secondDependency = secondDependency;
    }

    public String toString() {
        return "My Business Class is using constructor injection for : " + firstDepenedency + " and " + secondDependency;
    }    
}
package com.example.dependencyinjection;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

//If package is not specified @ComponentScan uses current package for scanning Beans
@ComponentScan
public class DependencyInjectionTypes {

    public static void main(String[] args) {
        try (var context = new AnnotationConfigApplicationContext(DependencyInjectionTypes.class)) {
            //Here we're not trying to explicitly get bean from context
            //Still the sysout indside constructor of MyBusinessClass 
            // will get printed due to eager initialization.
        }
    }
}

Output

Initialization

Example : Lazy Initialization

package com.example.dependencyinjection;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class MyBusinessClass {

    private final FirstDependency firstDepenedency;    
    private final SecondDependency secondDependency;

    public MyBusinessClass(FirstDependency firstDepenedency, SecondDependency secondDependency) {
        super();
        System.out.println("Initialization");
        this.firstDepenedency = firstDepenedency;
        this.secondDependency = secondDependency;
    }

    public String toString() {
        return "My Business Class is using constructor injection for : " + firstDepenedency + " and " + secondDependency;
    }    
}
package com.example.dependencyinjection;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

//If package is not specified @ComponentScan uses current package for scanning Beans
@ComponentScan
public class DependencyInjectionTypes {

    public static void main(String[] args) {
        try (var context = new AnnotationConfigApplicationContext(DependencyInjectionTypes.class)) {
            //Lazy initialization so nothing will get printed until
            //context.getBean(MyBusinessClass.class);
        }
    }
}

Conclusion

This article explains the concept of lazy initialization in Spring, detailing how it can improve resource management and reduce application start-up time for rarely used beans. It differentiates lazy initialization with the default eager initialization, which favors early detection of dependency injection and configuration issues. Practical examples are provided to illustrate both eager and lazy initialization approaches using `@Lazy` annotation.