ZetCode

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.

build.gradle
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.

resources/application.properties
spring.main.banner-mode=off
logging.level.org.springframework=ERROR

In the application.properties we turn off the banner and set the logging level.

com/zetcode/bean/MyBean.java
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.

com/zetcode/bean/MyLazyBean.java
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.

com/zetcode/bean/StartUpBean.java
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.

com/zetcode/controller/MyController.java
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.

resources/templates/showMessages.ftlh
<!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.

resources/static/index.html
<!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.

com/zetcode/Application.java
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.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Spring Boot tutorials.

AltStyle によって変換されたページ (->オリジナル) /