@Lazy介绍
@Lazy
注解是一个配置注解,用于指示 Spring 容器在创建 bean 时采用延迟初始化的策略。这意味着,除非 bean 被实际使用,否则不会被创建和初始化。
在 Spring 框架中,默认情况下,所有的单例 bean 在容器启动时都会被创建和初始化。但是,对于一些复杂的 bean,它们的初始化可能会比较耗时,或者它们依赖的资源在容器启动时可能还没有准备好。在这些情况下,使用 @Lazy
注解可以避免在容器启动时立即创建和初始化这些 bean,从而提高容器的启动速度,减少资源消耗。
@Lazy
注解可以应用于类级别,也可以应用于方法级别。当应用于类级别时,它指示 Spring 容器对该类创建的所有 bean 实例都采用延迟初始化策略。当应用于方法级别时,它指示 Spring 容器对该方法创建的 bean 实例采用延迟初始化策略。
需要注意的是,@Lazy
注解只对单例 bean 有效,对于原型 bean,由于每次获取 bean 时都会创建一个新的实例,因此不需要使用 @Lazy
注解。此外,如果一个 bean 依赖于其他 bean,并且这些依赖的 bean 没有被初始化,那么即使使用了 @Lazy
注解,Spring 容器也会在初始化该 bean 时创建和初始化这些依赖的 bean。
@Lazy源码
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lazy {
boolean value() default true;
}
源代码截图
@Lazy属性介绍
value:boolean类型的属性,表示是否延迟创建单例Bean,默认值为true。
- true:表示延迟创建单例Bean,此时在IOC启动时不会创建Bean对象,而是在第一次使用时创建单例Bean对象。
- false:表示不延迟创建单例Bean对象,IOC容器启动时,就会创建单例Bean对象。
@Lazy注解使用场景
使用场景主要集中在以下几种情况:
-
重量级 bean 的初始化:当你的应用中有一些初始化成本较高的 bean,例如需要连接到外部服务或加载大量数据的 bean 时,使用
@Lazy
可以推迟这些 bean 的初始化,直到它们真正被需要。 -
依赖关系中的循环依赖:在处理循环依赖时,
@Lazy
可以帮助打破依赖关系,确保 bean 能够在需要时才被创建。这通常用于解决两个或多个 bean 相互依赖,但不需要在应用启动时立即完全初始化的情况。 -
按需加载服务:在某些情况下,你可能希望服务或组件仅在首次请求时初始化,例如,当服务的初始化过程涉及到昂贵的 I/O 操作或复杂的计算时。这样可以提高应用的响应速度和启动性能。
-
懒加载关联对象:在处理关联对象时,如果关联对象的初始化不是应用启动时必须的,可以使用
@Lazy
来延迟加载这些关联对象,直到它们被访问。 -
避免启动时的阻塞:如果某些 bean 的初始化过程可能会阻塞应用的启动(例如,等待外部资源就绪),使用
@Lazy
可以确保应用能够快速启动,而不会因为等待这些资源而延迟。 -
优化测试过程:在进行单元测试时,
@Lazy
可以帮助减少测试环境的初始化时间,因为你可能不需要在测试时加载所有的 bean。 -
按需初始化的配置:有时候,你可能希望根据配置文件或环境变量来决定是否延迟加载某些 bean。在这种情况下,
@Lazy
可以与条件化配置结合使用,以实现更灵活的初始化策略。 -
服务的预热:在某些应用中,可能需要在应用启动后进行一些预热操作,如缓存预热。
@Lazy
可以用来延迟加载负责预热的服务,直到应用启动完成并且预热操作可以安全执行。
@Lazy测试示例代码
示例代码 一
LazyDemoBean类
package com.yang.SpringTest.annotation.lazyLearn;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author By: chengxuyuanshitang
* Package com.yang.SpringTest.annotation.lazyLearn
* Ceate Time 2024-03-21 16:02
*/
@Data
@Slf4j
public class LazyDemoBean {
public LazyDemoBean(){
log.info (" ---------- LazyDemoBean Init ----------");
}
}
LazyDemoConfig配资类
package com.yang.SpringTest.annotation.lazyLearn;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
/**
* <p>配置类</p>
*
* @author By: chengxuyuanshitang
* Package com.yang.SpringTest.annotation.lazyLearn
* Ceate Time 2024-03-21 16:07
*/
@Configuration
public class LazyDemoConfig {
@Bean
@Lazy
public LazyDemoBean lazyDemoBean () {
return new LazyDemoBean ();
}
}
LazyDemoTest测试类
package com.yang.SpringTest.annotation.lazyLearn;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* <p>测试类</p>
*
* @author By: chengxuyuanshitang
* Package com.yang.SpringTest.annotation.lazyLearn
* Ceate Time 2024-03-21 16:08
*/
@Slf4j
public class LazyDemoTest {
public static void main(String[] args) {
log.info("========== 创建IOC容器开始==========");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LazyDemoConfig.class);
log.info("==========创建IOC容器结束==========");
log.info("==========IOC容器中获取Bean开始==========");
LazyDemoBean demo1 = context.getBean(LazyDemoBean.class);
LazyDemoBean demo2 = context.getBean(LazyDemoBean.class);
log.info("**************** demo1是否等于demo2 : {}", (demo1 == demo2));
log.info("==========从IOC容器中获取Bean结束==========");
context.close();
}
}