Lazy Initialization in Spring Boot 2 – Spring Boot 2中的懒惰初始化

最后修改: 2019年 6月 19日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll see how to configure lazy initialization at the application level, starting with Spring Boot 2.2.

在本教程中,我们将看到如何在应用层面配置懒惰初始化,从Spring Boot 2.2.开始。

2. Lazy Initialization

2.懒惰的初始化

By default in Spring, all the defined beans, and their dependencies, are created when the application context is created.

在Spring中,默认情况下,所有定义的Bean以及它们的依赖关系都是在创建应用上下文时创建的。

In contrast, when we configure a bean with lazy initialization, the bean will only be created, and its dependencies injected, once they’re needed.

相反,当我们用懒惰初始化配置Bean时,只有在需要时才会创建Bean,并注入其依赖性。

3. The Maven Dependency

3.Maven的依赖性

In order to get Spring Boot in our application, we need to include it in our classpath.

为了在我们的应用程序中获得Spring Boot,我们需要将其纳入我们的classpath。

With Maven, we can just add the spring-boot-starter dependency:

使用Maven,我们只需添加spring-boot-starter dependency

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.4.3</version>
    </dependency>
</dependencies>

4. Enable Lazy Initialization

4.启用懒人初始化

Spring Boot 2 introduces the spring.main.lazy-initialization property, making it easier to configure lazy initialization across the whole application.

Spring Boot 2引入了spring.main.lazy-initialization属性,使得在整个应用中配置懒人初始化变得更加容易。

Setting the property value to true means that all the beans in the application will use lazy initialization.

将属性值设置为true意味着应用程序中的所有Bean将使用懒惰初始化。

Let’s configure the property in our application.yml configuration file:

让我们在我们的application.yml配置文件中配置这个属性。

spring:
  main:
    lazy-initialization: true

Or, if it’s the case, in our application.properties file:

或者,如果是这样,在我们的application.properties文件中。

spring.main.lazy-initialization=true

This configuration affects all the beans in the context. So, if we want to configure lazy initialization for a specific bean, we can do it through the @Lazy approach.

这种配置会影响上下文中的所有Bean。因此,如果我们想为特定的Bean配置懒惰初始化,我们可以通过@Lazy方法来实现。

Even more, we can use the new property, in combination with the @Lazy annotation, set to false.

甚至,我们可以使用新的属性,结合@Lazy注解,设置为false

Or in other words, all the defined beans will use lazy initialization, except for those that we explicitly configure with @Lazy(false).

或者换句话说,所有定义的Bean都将使用懒惰初始化,除了那些我们明确配置了@Lazy(false)的Bean。

4.1. Using SpringApplicationBuilder

4.1.使用SpringApplicationBuilder

Another way to configure the lazy initialization is to use the SpringApplicationBuilder method:

另一种配置懒惰初始化的方法是使用SpringApplicationBuilder方法。

SpringApplicationBuilder(Application.class)
  .lazyInitialization(true)
  .build(args)
  .run();

In the above example, we use the lazyInitialization method to control whether the application should be initialized lazily.

在上面的例子中,我们使用lazyInitialization方法来控制应用程序是否应该被懒散地初始化。

4.2. Using SpringApplication

4.2.使用SpringApplication

Alternatively, we can also use the SpringApplication class:

另外,我们也可以使用SpringApplication类。

SpringApplication app = new SpringApplication(Application.class);
app.setLazyInitialization(true);
app.run(args);

Here, we use the setLazyInitialization method to configure our application to be initialized lazily.

在这里,我们使用setLazyInitialization方法来配置我们的应用程序,使其懒惰地被初始化。

One important note to remember is that properties defined in the application property files take precedence over flags set using either SpringApplication or SpringApplicationBuilder.

需要记住的一个重要注意事项是:应用程序属性文件中定义的属性优先于使用SpringApplicationSpringApplicationBuilder设置的标志。

5. Run

5.运行

Let’s create a simple service that will enable us to test what we just described.

让我们创建一个简单的服务,使我们能够测试我们刚刚描述的内容。

By adding a message to the constructor, we’ll know exactly when the bean gets created.

通过给构造函数添加消息,我们就能准确地知道Bean何时被创建。

public class Writer {

    private final String writerId;

    public Writer(String writerId) {
        this.writerId = writerId;
        System.out.println(writerId + " initialized!!!");
    }

    public void write(String message) {
        System.out.println(writerId + ": " + message);
    }
    
}

Also, let’s create the SpringApplication and inject the service we’ve created before.

另外,让我们创建SpringApplication并注入我们之前创建的服务。

@SpringBootApplication
public class Application {

    @Bean("writer1")
    public Writer getWriter1() {
        return new Writer("Writer 1");
    }

    @Bean("writer2")
    public Writer getWriter2() {
        return new Writer("Writer 2");
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Application context initialized!!!");

        Writer writer1 = ctx.getBean("writer1", Writer.class);
        writer1.write("First message");

        Writer writer2 = ctx.getBean("writer2", Writer.class);
        writer2.write("Second message");
    }
}

Let’s set the spring.main.lazy-initialization property value to false, and run our application.

让我们把spring.main.lazy-initialization属性值设置为false,然后运行我们的应用程序。

Writer 1 initialized!!!
Writer 2 initialized!!!
Application context initialized!!!
Writer 1: First message
Writer 2: Second message

As we can see, the beans were created when the application context was starting up.

我们可以看到,这些Bean是在应用环境启动时创建的。

Now let’s change the value of spring.main.lazy-initialization to true, and run our application again.

现在让我们把spring.main.lazy-initialization的值改为true,并再次运行我们的应用程序。

Application context initialized!!!
Writer 1 initialized!!!
Writer 1: First message
Writer 2 initialized!!!
Writer 2: Second message

As a result, the application didn’t create the beans at startup time, but only when it needed them.

结果是,应用程序没有在启动时创建Bean,而是在需要时才创建。

6. Effects of Lazy Initialization

6.懒惰初始化的影响

Enabling lazy initialization in the whole application could produce both positive and negative effects.

在整个应用程序中启用懒惰初始化可能产生积极和消极的影响。

Let’s talk about some of these, as they’re described in the official announcement of the new functionality:

让我们来谈谈其中的一些内容,因为它们在新功能的官方公告中得到了描述。

  1. Lazy initialization may reduce the number of beans created when the application is starting – therefore, we can improve the startup time of the application
  2. As none of the beans are created until they are needed, we could mask issues, getting them in run time instead of startup time
  3. The issues can include out of memory errors, misconfigurations, or class-definition-found errors
  4. Also, when we’re in a web context, triggering bean creation on demand will increase the latency of HTTP requests – the bean creation will affect only the first request, but this may have a negative impact on load-balancing and auto-scaling.

7. Conclusion

7.结语

In this tutorial, we configured lazy initialization with the new property spring.main.lazy-initialization, introduced in Spring Boot 2.2.

在本教程中,我们用Spring Boot 2.2中引入的新属性spring.main.lazy-initialization配置了懒人初始化。

As always, the source code for this tutorial is available over on GitHub.

像往常一样,本教程的源代码可在GitHub上获得over