Spring Boot @Lazy
last modified July 23, 2023
In this article we show how to lazily intialize beans with Spring @Lazy annotation.
Spring is a popular Java application framework for creating enterprise applications. Spring Boot is an evolution of Spring framework which helps create stand-alone, production-grade Spring based applications with minimal effort.
@Lazy
@Lazy
annotation indicates whether a bean is to be
lazily initialized. It can be used on @Component
and
@Bean
definitions. A @Lazy
bean is not
initialized until referenced by another bean or explicitly retrieved
from BeanFactory
. Beans that are not annotated with @Lazy
are initialized eagerly.
Spring Boot @Lazy example
In the following example we create beans that are initialized lazily and eagerly. It demostrates the difference between the two types of beans. The application is a simple Spring Boot web application, which runs on embedded Tomcat server. We use Freemarker template engine.
build.gradle ... src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── Application.java │ │ ├── bean │ │ │ ├── MyBean.java │ │ │ ├── MyLazyBean.java │ │ │ └── StartUpBean.java │ │ └── controller │ │ └── MyController.java │ └── resources │ ├── application.properties │ ├── static │ │ └── index.html │ └── templates │ └── showMessages.ftlh └── test └── java
This is the project structure.
plugins { id 'org.springframework.boot' version '3.1.1' id 'io.spring.dependency-management' version '1.1.0' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-freemarker' }
This is the build.gradle
file.
spring.main.banner-mode=off logging.level.org.springframework=ERROR
In the application.properties
we turn off the banner and set
the logging level.
package com.zetcode.bean; import org.springframework.stereotype.Component; import java.util.logging.Logger; @Component public class MyBean { static Logger log = Logger.getLogger(MyBean.class.getName()); public MyBean() { log.info("MyBean initialized"); } public String getMessage() { return "Message from MyBean"; } }
This is MyBean
. This bean is initialized eagerly, that is,
at the start of the Spring framework.
package com.zetcode.bean; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import java.util.logging.Logger; @Component @Lazy public class MyLazyBean { static Logger log = Logger.getLogger(MyLazyBean.class.getName()); public MyLazyBean() { log.info("MyLazyBean initialized"); } public String getMessage() { return "Message from MyLazyBean"; } }
MyLazyBean
contains the @Lazy
annotation. It is
initialized lazily, when first requested. It is requested from the controller.
package com.zetcode.bean; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; import java.util.logging.Logger; @Component public class StartUpBean implements ApplicationListener<ApplicationReadyEvent> { static Logger log = Logger.getLogger(StartUpBean.class.getName()); @Override public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { log.info("Application is ready"); } }
StartUpBean
implements an application listener; it logs a message
when the application is ready.
package com.zetcode.controller; import com.zetcode.bean.MyBean; import com.zetcode.bean.MyLazyBean; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class MyController { private final BeanFactory factory; @Autowired public MyController(BeanFactory factory) { this.factory = factory; } @GetMapping(path="/messages") public String getMessages(Model model) { MyLazyBean myLazyBean = factory.getBean(MyLazyBean.class); MyBean myBean = factory.getBean(MyBean.class); model.addAttribute("mybean", myBean.getMessage()); model.addAttribute("mylazybean", myLazyBean.getMessage()); return "showMessages"; } }
This is a controller class. It creates the two beans and receives their messages. The messages are displayd in a Freemarker template.
private final BeanFactory factory; @Autowired public MyController(BeanFactory factory) { this.factory = factory; }
We inject the BeanFactory
. The factory is used for accessing
Spring beans.
MyLazyBean myLazyBean = factory.getBean(MyLazyBean.class);
This is the moment when the MyLazyBean
is initialized.
MyBean myBean = factory.getBean(MyBean.class);
We get the MyBean
from the factory; MyBean
was initialized at Spring's startup.
<!DOCTYPE html> <html> <head> <title>Show data</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <p> MyBean: ${mybean} </p> <p> MyLazyBean: ${mylazybean} </p> </body> </html>
The Freemarker template displays the messages from the two beans.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Home page</title> </head> <body> <a href="messages">Get messages</a> </body> </html>
In the index.html
there is a link to get the messages from
beans.
package com.zetcode; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
The Application
sets up the Spring Boot application.
The @SpringBootApplication
enables auto-configuration and
component scanning.
$ ./gradlew bootRun
We start the application.
Initializing Spring embedded WebApplicationContext com.zetcode.bean.MyBean : MyBean initialized com.zetcode.Application : Started Application in 2.483 seconds (JVM running for 2.854) com.zetcode.bean.StartUpBean : Application is ready
We can see these log messages when Spring Boot starts. Notice that MyBean
was initialized at startup.
com.zetcode.bean.MyLazyBean : MyLazyBean initialized
When the controller is called, the MyLazyBean
is initialized.
In this article we have showed how to use Spring @Lazy
annotation.