Starting Spring 4.0.0, @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 jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
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();
}
} OutputMyEagerBean 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 ProjectDependencies and Technologies Used: - spring-context 6.1.2 (Spring Context)
Version Compatibility: 4.0.0.RELEASE - 6.1.2 Version compatibilities of spring-context with this example: Versions in green have been tested.
- jakarta.jakartaee-api 10.0.0 (Eclipse Foundation)
- JDK 17
- Maven 3.8.1
|