How does Lazy annotation work in Spring?


@Lazy is an annotation used to delay the initialization of a Spring bean until it is actually needed (i.e., first used).

By default, Spring creates all singleton beans at startup (eager initialization). With @Lazy, you say: “Don’t create this bean now — create it only when someone asks for it.”

Why Use @Lazy?

  • Improve startup time (especially for heavy or rarely used beans)
  • Avoid circular dependencies in some cases
  • Save resources by loading beans on-demand

How to Use @Lazy

1. On a @Bean method (in @Configuration)

@Configuration
public class AppConfig {

    @Bean
    @Lazy
    public HeavyService heavyService() {
        System.out.println("Creating HeavyService... (this will print later)");
        return new HeavyService();
    }

    @Bean
    public LightService lightService(HeavyService heavyService) {
        System.out.println("Creating LightService...");
        return new LightService(heavyService);
    }
}

Supporting Classes

public class HeavyService {
    public HeavyService() {
        System.out.println("HeavyService constructor called!");
    }
}

public class LightService {
    private final HeavyService heavyService;

    public LightService(HeavyService heavyService) {
        this.heavyService = heavyService;
    }
}

2. On a @Component class

@Component
@Lazy
public class DatabaseConnection {
    public DatabaseConnection() {
        System.out.println("DatabaseConnection created! (only when used)");
    }
}

Example: See the Difference

@SpringBootApplication
public class LazyDemoApplication {

    public static void main(String[] args) {
        var context = SpringApplication.run(LazyDemoApplication.class, args);

        System.out.println("--- App started ---");

        // This triggers lazy bean creation
        HeavyService service = context.getBean(HeavyService.class);
        System.out.println("Got HeavyService: " + service);
    }
}

Output:

--- App started ---
Creating HeavyService... (this will print later)
HeavyService constructor called!
Got HeavyService: com.example.HeavyService@...

Notice: HeavyService is not created at startup — only when getBean() is called.


@Lazy on @Configuration Class?

Yes! You can apply it to the whole config:

@Configuration
@Lazy
public class LazyConfig { ... }

This makes all beans in that config class lazy.


Important Notes

Point Explanation
Only works for singleton beans Default scope is singleton
Proxy-based Spring creates a proxy that initializes the real bean on first use
@Autowired + @Lazy If you inject a lazy bean, it won’t be created until the dependent bean is used

Simple Analogy

Think of @Lazy like ordering food delivery:

  • Without @Lazy: You cook food at 8 AM even if you eat at 8 PM → waste of time
  • With @Lazy: You order food only when you’re hungry → faster startup, fresh food

Summary

Annotation When is bean created?
No @Lazy At application startup
@Lazy On first use (lazy)

Use @Lazy when:

  • Bean is expensive to create
  • Bean is rarely used
  • You want faster startup