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 地址。