Spring Boot v2.2.0
Spring Boot v2.2.0 has been released and is now GA.
So, let's examine one of its functions, Lazy Initialization.
Spring Boot 2.2.0 Release v2.2.0.RELEASE · spring-projects/spring-boot · GitHub Spring Boot 2.2 Release Notes · spring-projects/spring-boot Wiki · GitHub Spring Boot Reference Documentation
The Hinagata Project is created from Spring Initializr.
Gradle I have confirmed that Gradle 5.6.2 is applied to the Gradle project created by Spring Initializr.
> gradlew -version
------------------------------------------------------------
Gradle 5.6.2
------------------------------------------------------------
Build time: 2019-09-05 16:13:54 UTC
Revision: 55a5e53d855db8fc7b0e494412fc624051a8e781
Kotlin: 1.3.41
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM: 13-ea (Oracle Corporation 13-ea+33)
OS: Windows 10 10.0 amd64
Lazy Initialization is to generate the bean managed by ApplicationContext when the target bean is called, not when the application is started (≒ ApplicationContext is initialized).
This mechanism has been available from previous versions, but from v2.2.0, Lazy Initialization will be applied uniformly by applying true to propertyspring.main.lazy-initialization
.
spring:
main:
lazy-initialization: true
package jp.co.musako.domain.model;
public class LazyInitializationDemoBean {
private String message;
public LazyInitializationDemoBean(String message) {
this.message = message;
System.out.println("call constructor " + this.message);
}
public void writer(String message){
System.out.println(this.message + " is " + message);
}
}
package jp.co.musako.config;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean("lazyInitializationDemoBean1")
public LazyInitializationDemoBean lazyInitializationDemoBean1(){
return new LazyInitializationDemoBean("create lazyInitializationDemoBean1");
}
@Bean("lazyInitializationDemoBean2")
public LazyInitializationDemoBean lazyInitializationDemoBean2(){
return new LazyInitializationDemoBean("create lazyInitializationDemoBean2");
}
}
package jp.co.musako;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Initialize Application Context");
LazyInitializationDemoBean bean1 = ctx.getBean("lazyInitializationDemoBean1", LazyInitializationDemoBean.class);
bean1.writer("first bean");
LazyInitializationDemoBean bean2 = ctx.getBean("lazyInitializationDemoBean2", LazyInitializationDemoBean.class);
bean2.writer("second bean");
}
}
Execution result
>gradlew bootRun
> Task :bootRun
2019-10-23 18:16:37.620 INFO 12708 --- [ main] jp.co.musako.Application : Started Application in 4.295 seconds (JVM running for 4.933)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
call constructor lazyInitializationDemoBean2
lazyInitializationDemoBean2 is second bean
Here, you can see that the processing is done in the following order.
There are the following ways to exclude a specific bean from LazyInitialization while applying LazyInitialization to the project by setting spring.main.lazy-initialization = true
.
@ org.springframework.context.annotation.Lazy (false)
to Bean
package jp.co.musako.config;
import jp.co.musako.domain.model.ExcludeLazyInitializationDemoBean;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.LazyInitializationExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
public class Config {
@Bean
static LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
return LazyInitializationExcludeFilter.forBeanTypes(ExcludeLazyInitializationDemoBean.class);
}
//Lazy Initialization applicable
@Bean("lazyInitializationDemoBean1")
public LazyInitializationDemoBean lazyInitializationDemoBean1(){
return new LazyInitializationDemoBean("lazyInitializationDemoBean1");
}
//Not applicable to Lazy Initialization
@Bean("lazyInitializationDemoBean2")
@Lazy(false)
public LazyInitializationDemoBean lazyInitializationDemoBean2(){
return new LazyInitializationDemoBean("lazyInitializationDemoBean2");
}
//Not applicable to Lazy Initialization
@Bean
public ExcludeLazyInitializationDemoBean ExcludeLazyInitializationDemoBean(){
return new ExcludeLazyInitializationDemoBean("excludeLazyInitializationDemoBean");
}
}
package jp.co.musako;
import jp.co.musako.domain.model.ExcludeLazyInitializationDemoBean;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Initialize Application Context");
LazyInitializationDemoBean bean1 = ctx.getBean("lazyInitializationDemoBean1", LazyInitializationDemoBean.class);
bean1.writer("first bean");
LazyInitializationDemoBean bean2 = ctx.getBean("lazyInitializationDemoBean2", LazyInitializationDemoBean.class);
bean2.writer("second bean");
ExcludeLazyInitializationDemoBean ExcludeLazyInitializationBean = ctx.getBean("ExcludeLazyInitializationDemoBean", ExcludeLazyInitializationDemoBean.class);
ExcludeLazyInitializationBean.writer("third bean");
}
}
>gradlew bootRun
> Task :bootRun
call constructor lazyInitializationDemoBean2
call constructor excludeLazyInitializationDemoBean
2019-10-23 18:52:52.464 INFO 6004 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-10-23 18:52:52.468 INFO 6004 --- [ main] jp.co.musako.Application : Started Application in 2.978 seconds (JVM running for 3.454)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
lazyInitializationDemoBean2 is second bean
excludeLazyInitializationDemoBean is third bean
As mentioned above, of the three beans defined in Config.java, only lazyInitializationDemoBean1 is the target of LazyInitialization.
Click here for source code: GitHub --forests-k / spring-boot-lazy-initialization : Spring Boot v2.2.0 lazy-initialization sample
The advantage of introducing Lazy Intialization is that it speeds up application startup and it does not waste memory because it initializes when needed.
However, initializing the bean and holding the bean in the container when necessary changes the life cycle of the bean so far, and the maximum number of beans held in the container (= memory occupancy) It may not be visible, so it may be possible that it has an impact on CPU load and load average, that is, you should not over-reliance on Lazy Initialization.
Therefore, it is necessary to consider conducting tests such as temporarily disabling Lazy Initialization in a test environment or an environment equivalent to production.
ref
Recommended Posts