Spring Boot

Spring Boot Lazy Initialization Example

Lazy Bean’s initialization is not a new topic for Spring developers.

The spring framework supports lazy-init from over 10 years.

By enabling lazy loading ( lazy-init="true" ) for a bean, we tell spring container to not to create that bean until it’s needed.

So, what is new in the spring boot lazy initialization feature that is introduced in the spring boot 2.0 version?.

What is new in Spring Boot Lazy Initialization

To understand the benefits of lazy initialization, let’s create a demo on spring lazy initialization.

At first, go to spring initializr and generate a new project. Don’t forget to select spring boot 2.2.0 M4 version.

Lazy Initialization in Spring Boot
Generate Spring Boot Project

Now download and extract this project and import it in eclipse or STS.

After importing the project, create two new packages and classes for controllers and services.

Project Structure

Inside LazyController.java

package com.codedelay.lazy.controller;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.codedelay.lazy.service.LazyService;

@RestController
@RequestMapping("/api")
public class LazyController {
	private static final String TAG = "LazyController";
	
	@Autowired
	private LazyService mService;
	
	@GetMapping("/welcome")
	public String welcomeMessage() {
		System.out.println(TAG + " Welcome ");
		return mService.welcomeMessage();
	}
	
	@PostConstruct
	public void init() {
		System.out.println(TAG + " init called ");
	}
}

LazyService.java

package com.codedelay.lazy.service;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Service;

@Service
public class LazyService {
	private static final String TAG = "LazyService";

	public String welcomeMessage() {
		System.out.println(TAG + " Welcome ");
		return "Welcome";
	}
	
	@PostConstruct
	public void init() {
		System.out.println(TAG + " init called ");
	}
}

Now let’s run the application to see how long it takes to start our application.

2019-07-25 13:45:45.150  INFO 12824 - – [           main] c.c.l.LazyIntializationDemoApplication   : Starting LazyIntializationDemoApplication on W108W438S2 with PID 12824 (C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo\target\classes started by Arpit_Nanavati in C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo)
2019-07-25 13:45:45.154  INFO 12824 - – [           main] c.c.l.LazyIntializationDemoApplication   : No active profile set, falling back to default profiles: default
2019-07-25 13:45:46.614  INFO 12824 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-07-25 13:45:46.625  INFO 12824 - – [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-07-25 13:45:46.625  INFO 12824 - – [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.21]
2019-07-25 13:45:46.764  INFO 12824 - – [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-07-25 13:45:46.765  INFO 12824 - – [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1535 ms
LazyService init called 
LazyController init called 
2019-07-25 13:45:46.956  INFO 12824 - – [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-07-25 13:45:47.148  INFO 12824 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-07-25 13:45:47.153  INFO 12824 - – [           main] c.c.l.LazyIntializationDemoApplication   : Started LazyIntializationDemoApplication in 2.472 seconds (JVM running for 2.939)

As you could see in the above logs, our application took 1535 ms to initialize and 2.472 seconds to start the app.

Did you observe that even we haven’t called REST api /api/welcome, but spring container still initialized LazyService?

LazyService init called 
LazyController init called 

Sometimes it is not a good idea to initialize bean until it is used.

Therefore, How can we improve the performance of the above code?

Let’s optimize the above program using spring boot lazy initialization.

To enable lazy initialization, open application.properties and below code

spring.main.lazy-initialization=true

And re-run the program.

2019-07-25 13:55:14.679  INFO 19452 - – [           main] c.c.l.LazyIntializationDemoApplication   : Starting LazyIntializationDemoApplication on W108W438S2 with PID 19452 (C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo\target\classes started by Arpit_Nanavati in C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo)
2019-07-25 13:55:14.682  INFO 19452 - – [           main] c.c.l.LazyIntializationDemoApplication   : No active profile set, falling back to default profiles: default
2019-07-25 13:55:16.080  INFO 19452 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-07-25 13:55:16.093  INFO 19452 - – [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-07-25 13:55:16.093  INFO 19452 - – [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.21]
2019-07-25 13:55:16.235  INFO 19452 - – [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-07-25 13:55:16.235  INFO 19452 - – [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1493 ms
2019-07-25 13:55:16.399  INFO 19452 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-07-25 13:55:16.404  INFO 19452 - – [           main] c.c.l.LazyIntializationDemoApplication   : Started LazyIntializationDemoApplication in 2.227 seconds (JVM running for 2.724)

From the above logs, it is clear that spring took only 1493 ms initialization, and 2.227seconds to start the application.

You may think that there is not a huge difference in application startup.

But if there are many controllers, services, config classes are present then you will find a significant difference.

Additionally, if you notice LazyService and LazyController are not yet called.

Not let’s hit API from the browser.

in my case it is http://localhost:8080/api/welcome .

2019-07-25 14:01:35.653  INFO 9136 - – [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-07-25 14:01:35.653  INFO 9136 - – [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-07-25 14:01:35.820  INFO 9136 - – [nio-8080-exec-1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-07-25 14:01:35.907  INFO 9136 - – [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 253 ms
LazyService init called 
LazyController init called 
LazyController Welcome 
LazyService Welcome 

As you can see, once you hit API, then only spring container will initialize process service.

Enable Lazy Initialization using @Lazy

If you don’t want to enable lazy initialization for all classes. You can also use @Lazy annotation.

public class LazyController {
	
	@Autowired
	@Lazy
	private LazyService mService;
@Service
@Lazy
public class LazyService {

In the above LazyController class, we have annotated LazyService property with @Lazy.

Also, we have an annotated Service class with @Lazy.

Let’s re-run the application

2019-07-25 14:07:44.751  INFO 1816 - – [           main] c.c.l.LazyIntializationDemoApplication   : Starting LazyIntializationDemoApplication on W108W438S2 with PID 1816 (C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo\target\classes started by Arpit_Nanavati in C:\Codedelay\lazy-intialization-demo\lazy-intialization-demo)
2019-07-25 14:07:44.755  INFO 1816 - – [           main] c.c.l.LazyIntializationDemoApplication   : No active profile set, falling back to default profiles: default
2019-07-25 14:07:46.166  INFO 1816 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-07-25 14:07:46.178  INFO 1816 - – [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-07-25 14:07:46.178  INFO 1816 - – [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.21]
2019-07-25 14:07:46.317  INFO 1816 - – [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-07-25 14:07:46.318  INFO 1816 - – [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1504 ms
LazyController init called 
2019-07-25 14:07:46.553  INFO 1816 - – [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-07-25 14:07:46.734  INFO 1816 - – [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-07-25 14:07:46.740  INFO 1816 - – [           main] c.c.l.LazyIntializationDemoApplication   : Started LazyIntializationDemoApplication in 2.482 seconds (JVM running for 2.932)

Now, you can see that only LazyService is not initialized now.

Click to rate this post!
[Total: 0 Average: 0]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.