Spring IoC(ApplicationContext)容器一般都会在启动的时候实例化所有单实例 Bean。如果我们想要 Spring 在启动的时候延迟加载 Bean,即在调用某个 Bean 的时候再去初始化,那么就可以使用 @Lazy 注解。
@Lazy 注解用来告诉 Spring 是否要延迟初始化指定的Bean。该注解可用于直接或间接用了 @Component 注解的任何类,或用了@Bean注释的方法。
如果 @Component 或 @Bean 定义上不存在 @Lazy 注解,则会进行初始化。如果存在 @Lazy 注解且设置 value为true,则 @Bean或 @Component 定义的 Bean 将不会被初始化,直到被另一个 Bean 引用或从封闭的 BeanFactory 中显式检索。如果存在 @Lazy 且设置 value 为false,则将在执行启动单例初始化的Bean工厂启动时实例化Bean。
如果 @Configuration 类上存在 @Lazy 注解,则表明该 @Configuration 中的所有 @Bean 方法都应延迟初始化。如果在 @Lazy 注解的 @Configuration 类中的 @Bean方法上存在 @Lazy 注解且设置 value 为 false,则表明重写了“默认延迟”行为,并且应立即初始化Bean。
除了 @Lazy 在组件初始化中的作用外,还可以将该注解放置在标有 @Autowired 或 @Inject 的注入点上:在这种情况下,它会为所有受影响的依赖项创建一个惰性解析代理,以替代使用ObjectFactory 或 Provider。
是否应该进行延迟初始化,true 表示开启延迟初始化,false 表示不开启延迟初始化。默认为 true。
(1)定义一个 MyConfig 类,该类上面添加了 @Lazy 注解,该注解将延迟该类下的 myBean 初始化,只有当我们用到 MyBean 的时候才会去初始化。如下:
package com.huangx.springboot.springboot_lazy_demo1.config;
import com.huangx.springboot.springboot_lazy_demo1.bean.MyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
@Lazy
public class MyConfig {
    @Bean
    public MyBean myBean() {
        System.out.println("===> init MyBean");
        return new MyBean("Welcome to SpringBoot.");
    }
}(2)下面定义了 MyConfig2 类,该类有两个 @Bean 方法,一个返回 MyBena2,另一个返回 ArrayList,其中 myBean2() 方法上面有 @Lazy 注解,表示该 Bean 将延迟初始化。代码如下:
package com.huangx.springboot.springboot_lazy_demo1.config;
import com.huangx.springboot.springboot_lazy_demo1.bean.MyBean2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import java.util.ArrayList;
@Configuration
public class MyConfig2 {
    @Bean
    @Lazy
    public MyBean2 myBean2() {
        System.out.println("===> init MyBean2");
        return new MyBean2("Welcome to SpringBoot.");
    }
    @Bean
    public ArrayList arrayList() {
        System.out.println("===> init ArrayList");
        return new ArrayList<>();
    }
}(3)定义客户端代码,用来调用前面 MyConfig 和 MyConfig2 中定义的 Bean,用来验证 Bean 是否在使用的时候才初始化。代码如下:
package com.huangx.springboot.springboot_lazy_demo1;
import com.huangx.springboot.springboot_lazy_demo1.bean.MyBean;
import com.huangx.springboot.springboot_lazy_demo1.bean.MyBean2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class SpringbootLazyDemo1Application {
    @Autowired
    private ApplicationContext applicationContext;
    public static void main(String[] args) {
        SpringApplication.run(SpringbootLazyDemo1Application.class, args);
    }
    @RequestMapping("/demo1")
    public String demo1() {
        MyBean myBean = applicationContext.getBean(MyBean.class);
        return myBean.getSummary();
    }
    @RequestMapping("/demo2")
    public String demo2() {
        MyBean2 myBean = applicationContext.getBean(MyBean2.class);
        return myBean.getSummary();
    }
}启动 Spring Boot 程序,通过浏览器分别访问 localhost:8080/demo1 和 localhost:8080/demo2 地址。
