当你有两个 service 时,他们的业务互相关联,比如:用户service需要查询订单service,同时订单service又需要通过用户service来查询用户
这样就会形成一个闭环,如下:

UserService:
@Service
public class UserService {
@Autowired
private OrderService orderService;
public Order getUserOrder(Long userId) {
return orderService.getOrderByUser(userId);
}
public User getUser(Long userId) {
// 模拟查询后User
User user = new User();
user.setId(1L);
return user;
}
}
OrderService:
@Service
public class OrderService {
@Autowired
private UserService userService;
public Order getOrderByUser(Long userId) {
User user = userService.getUser(userId);
Order order = new Order();
order.setOrderId("xxx");
order.setAmount(100L);
order.setUserId(user.getId());
return order;
}
}
使用时,会报错如下:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderService': Unsatisfied dependency expressed through field 'userService': Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'orderService': Error creating bean with name 'orderService': Requested bean is currently in creation: Is there an unresolvable circular reference or an asynchronous initialization dependency?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:767)
.....
给 UserService依赖添加 @lazy
@Lazy
@Autowired
private UserService userService;
[!TIP]
什么是 @lazy
@Lazy 是 Spring 框架中的一个注解,用于实现 Bean 的延迟初始化。
核心概念
默认行为 vs @Lazy
场景 初始化时机 默认(无@Lazy) Spring 容器启动时立即创建 Bean 使用 @Lazy 首次从容器获取 Bean 时才创建
使用方式
1️⃣ 类级别使用
@Component @Lazy // 整个类延迟初始化 public class ExpensiveService { public ExpensiveService() { System.out.println("ExpensiveService 被创建了!"); // 假设这里有耗时的初始化操作 } public void doSomething() { System.out.println("执行操作..."); } }2️⃣ 配置类中使用
@Configuration public class AppConfig { @Bean @Lazy // 该 Bean 延迟初始化 public DataSource dataSource() { System.out.println("创建数据库连接池..."); return new HikariDataSource(); } }3️⃣ 注入时使用(推荐)
@Service public class OrderService { private final ExpensiveService expensiveService; @Autowired @Lazy // 注入时标记为延迟加载 public OrderService(ExpensiveService expensiveService) { this.expensiveService = expensiveService; } }
工作原理图解
┌─────────────────────────────────────────────────────┐ │ Spring 容器启动 │ ├─────────────────────────────────────────────────────┤ │ │ │ @Component @Component @Lazy │ │ ┌─────────┐ ┌─────────────┐ │ │ │ ServiceA │ │ ServiceB │ ← 不创建! │ │ │ ✓创建 │ │ (仅注册) │ │ │ └─────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ ▼ 当首次使用 ServiceB 时 ┌─────────────────────────────────────────────────────┐ │ ServiceB 首次被调用 │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ │ │ │ ServiceB │ ← 此时才真正创建! │ │ │ ✓创建 │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────┘
实际应用场景
场景1:解决循环依赖
@Service public class ServiceA { @Autowired @Lazy // 打破循环依赖 private ServiceB serviceB; } @Service public class ServiceB { @Autowired private ServiceA serviceA; }场景2:重量级资源延迟加载
@Service public class ReportService { @Lazy @Autowired private MLModelService mlModelService; // 加载大型机器学习模型 public Report generateReport() { // 只有在生成报告时才加载模型 return mlModelService.analyze(); } }场景3:可选功能
@Component public class PaymentService { @Lazy @Autowired(required = false) private Optional<wechatpayservice> wechatPay; // 可选的微信支付 public void pay() { wechatPay.ifPresent(service -> service.pay()); } }
全局延迟配置(Spring Boot)
在
application.yml中可以全局开启延迟初始化:spring: main: lazy-initialization: true # 所有 Bean 都延迟初始化
注意事项
注意点 说明 单例特性不变 @Lazy Bean 仍然是单例,首次创建后会缓存 @Lazy 失效情况 被 @PostConstruct、SmartInitializingSingleton等主动触发时可能失效测试困难 延迟加载的 Bean 在测试中可能需要额外处理 启动快,首次慢 启动时间缩短,但首次调用会有延迟
总结
@Lazy = 推迟 Bean 的创建时机 何时使用? ├── 解决循环依赖 ├── 减少启动时间(轻量级应用) ├── 延迟加载重量级资源 └── 可选/按需加载的功能
在Spring2.6前,Spring遇到这种情况会自动帮你兜底,除了你自己用构造器创建的bean。
但后续删了这个特性,因为这样子的情况本就是设计问题,使用 @lazy 只是缓兵之计。

暂无评论,欢迎第一个留言。
评论