# Spring Boot `@Lazy`教程

> 原文： [http://zetcode.com/springboot/lazybean/](http://zetcode.com/springboot/lazybean/)

Spring Boot `@Lazy`教程展示了如何使用 Spring `@Lazy`注解懒惰地初始化 bean。

Spring 是用于创建企业应用的流行 Java 应用框架。 Spring Boot 是 Spring 框架的演进，可帮助您轻松创建独立的，生产级的基于 Spring 的应用。

## `@Lazy`

`@Lazy`注解指示是否要延迟初始化 bean。 它可以用于`@Component`和`@Bean`定义。 `@Lazy` bean 不会被初始化，直到被另一个 bean 引用或从`BeanFactory`中显式检索。 不使用`@Lazy`注解的 Bean 会被初始化。

## Spring Boot `@Lazy`示例

在下面的示例中，我们创建延迟懒惰地初始化的 bean。 它说明了两种类型的 bean 之间的区别。 该应用是一个简单的 Spring Boot Web 应用，可在嵌入式 Tomcat 服务器上运行。 我们使用 Freemarker 模板引擎。

```java
$ 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

```

这是项目结构。

`pom.xml`

```java
<?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 启动器是一组方便的依赖项描述符，可以极大地简化 Maven 配置。 `spring-boot-starter-parent`具有 Spring Boot 应用的一些常用配置。 `spring-boot-starter-freemarker`是使用 Freemarker 视图构建 MVC Web 应用的入门工具。

在`spring-boot-maven-plugin`提供了 Maven 的 Spring Boot 支持，使我们能够打包可执行的 JAR 或 WAR 档案。 它的`spring-boot:run`目标运行 Spring Boot 应用。

`application.properties`

```java
server.port=8086
server.contextPath=/myapp

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

```

在`application.properties`文件中，我们编写了 Spring Boot 应用的各种配置设置。 完成这些设置后，我们可以通过`localhost:8086/myapp/`访问该应用。

`MyBean.java`

```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";
    }
}

```

这是`MyBean`。 急切地初始化该 bean，即在 Spring 框架开始时。

`MyLazyBean.java`

```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`包含`@Lazy`注解。 第一次请求时，它会延迟地初始化。 从控制器请求。

`StartUpBean.java`

```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`实现一个应用监听器； 当应用准备就绪时，它将记录一条消息。

`MyController.java`

```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";
    }
}

```

这是一个控制器类。 它创建两个 bean 并接收它们的消息。 消息显示在 Freemarker 模板中。

```java
@Autowired
private BeanFactory factory;

```

我们注入`BeanFactory`。 工厂用于访问 Spring bean。

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

```

此时，`MyLazyBean`被初始化。

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

```

我们从工厂获得了`MyBean`； `MyBean`在 Spring 的启动时初始化。

`showMessages.ftl`

```java
<!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>

```

Freemarker 模板显示来自两个 bean 的消息。

`index.html`

```java
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>

<a href="messages">Get messages</a>

</body>
</html>

```

`index.html`中有一个链接，用于从 Bean 获取消息。

`Application.java`

```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);
    }
}

```

`Application`设置 Spring Boot 应用。 `@SpringBootApplication`启用自动配置和组件扫描。

```java
$ mvn spring-boot:run 

```

应用运行后，我们可以导航到`localhost:8086/myapp/`。

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

```

当 Spring 启动时，我们可以看到这些日志消息。 请注意，`MyBean`在启动时已初始化。

```java
com.zetcode.bean.MyLazyBean : MyLazyBean initialized

```

调用控制器时，将初始化`MyLazyBean`。

在本教程中，我们展示了如何使用 Spring `@Lazy`注解。 您可能也对相关教程感兴趣：

*   [Spring Boot PostgreSQL 教程](/springboot/postgresql/)
*   [Spring Boot `@Bean`](/articles/springbootbean/)
*   [Spring Boot `@Qualifier`注解](/articles/springbootqualifier/)