Ebooks

Spring Boot @Lazy tutorial

Spring Boot @Lazy tutorial shows 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.

$ tree
.
├── pom.xml
├── SpringBootLazy.iml
└── 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.ftl
    └── test
        └── java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>SpringBootLazy</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Spring Boot starters are a set of convenient dependency descriptors which greatly simplify Maven configuration. The spring-boot-starter-parent has some common configurations for a Spring Boot application. The spring-boot-starter-freemarker is a starter for building MVC web applications using Freemarker views.

The spring-boot-maven-plugin provides Spring Boot support in Maven, allowing us to package executable JAR or WAR archives. Its spring-boot:run goal runs the Spring Boot application.

application.properties
server.port=8086
server.contextPath=/myapp

spring.main.banner-mode=off
logging.level.org.springframework=ERROR

In the application.properties file we write various configuration settings of a Spring Boot application. After these settings, we access the application at localhost:8086/myapp/.

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.

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.

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.

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 {

    @Autowired
    private BeanFactory factory;

    @GetMapping(value="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.

@Autowired
private BeanFactory factory;

We inject the BeanFactory. The factory is used for accessing Spring beans.

MyLazyBean myLazyBean = factory.getBean(MyLazyBean.class);

This is the moment, where the MyLazyBean gets initialized.

MyBean myBean = factory.getBean(MyBean.class);

We get the MyBean from the factory; MyBean was initialized at Spring's startup.

showMessages.ftl
<!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.

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.

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.

$ mvn spring-boot:run 

After the application is run, we can navigate to localhost:8086/myapp/.

Initializing Spring embedded WebApplicationContext
com.zetcode.bean.MyBean : MyBean initialized
com.zetcode.bean.StartUpBean : Application is ready

We can see these log messages, when Spring 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 tutorial, we have showed how to use Spring @Lazy annotation. You might also be interested in the related tutorials: