Close

Spring - Using @Lazy at Injection points

[Last Updated: Mar 14, 2021]

Starting Spring 4.3, @Lazy can be used at injection points as well. That means we can place @Lazy along with @Autowired or @Inject or @Resource. That will delay the target bean initialization until it is used by the injection point class, even though the injection point class has been initialized earlier.


Example

An eagerly initialized bean

Following is MyEagerBean which has an @Autowired annotation (an injection point). This bean will eagerly initialized and that will cause to initialize all it's dependencies as well, unless we use @Lazy at a given injection point:

package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import javax.annotation.PostConstruct;

public class MyEagerBean {

  @Autowired
  @Lazy
  private MyLazyBean myLazyBean;

  @PostConstruct
  public void init () {
      System.out.println(getClass().getSimpleName() + " has been initialized");
  }

  public void doSomethingWithLazyBean () {
      System.out.println("Using lazy bean");
      myLazyBean.doSomething();
  }
}

The lazily initialized bean

public class MyLazyBean {

  @PostConstruct
  public void init () {
      System.out.println(getClass().getSimpleName() + " has been initialized");
  }

  public void doSomething () {
      System.out.println("inside lazy bean doSomething()");
  }
}

Main class

public class LazyExampleMain {

  public static void main (String[] args) {
      ApplicationContext context =
                new AnnotationConfigApplicationContext(
                          MyConfig.class);
      System.out.println("--- container initialized ---");
      MyEagerBean bean = context.getBean(MyEagerBean.class);
      System.out.println("MyEagerBean retrieved from bean factory");
      bean.doSomethingWithLazyBean();
  }
}

Output

MyEagerBean has been initialized
--- container initialized ---
MyEagerBean retrieved from bean factory
Using lazy bean
MyLazyBean has been initialized
inside lazy bean doSomething()

Now if we comment out @Lazy from MyEagerBean:

public class MyEagerBean {

  @Autowired
  //@Lazy
  private MyLazyBean myLazyBean;
  .......
}

Output:

MyLazyBean has been initialized
MyEagerBean has been initialized
--- container initialized ---
MyEagerBean retrieved from bean factory
Using lazy bean
inside lazy bean doSomething()

When MyEagerBean is loaded, it will cause to initialize all it's dependencies unless we use @Lazy at injection point too. The usage of @Lazy in factory class MyConfig prevents loading bean during 'startup' until it's used first time in the application.

In short:

@Lazy with @Bean (or @Lazy with @Component): don't load eagerly during application start up, until it's used in the application

@Lazy with @Autowired : don't load during outer class initialization, until it's first used by the application.


How that works?

Spring creates and uses a lazy-resolution proxy object for the injection point (the one annotated with @Autowired and @Lazy) instead of initializing the object directly.


Example Project

Dependencies and Technologies Used:

  • spring-context 4.3.6.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.3.9

Using @Lazy at Injection points Select All Download
  • spring-lazy-injection-point
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyEagerBean.java

    See Also