模块依赖与循环依赖约束
Forge 对模块间的依赖关系有严格约束,违反约束会导致编译失败或运行时异常。
依赖方向
forge-framework(框架层)
├── forge-dependencies(BOM)
├── forge-starter-parent(技术启动器)
│ └── forge-starter-*(各 Starter)
└── forge-plugin-parent(业务插件)
└── forge-plugin-*(各 Plugin)
↓
forge-business(业务模块)
↓
forge-admin-server(主应用)依赖规则
| 规则 | 说明 |
|---|---|
| Starter → Starter | 允许(如 cache 依赖 core) |
| Plugin → Starter | 允许 |
| Plugin → Plugin | 禁止互相注入 |
| 业务模块 → Starter | 允许 |
| 业务模块 → Plugin | 允许 |
| Starter → Plugin | 禁止反向依赖 |
| Starter → 业务模块 | 禁止反向依赖 |
禁止互相注入
Plugin 之间的 Service 禁止互相注入,这是 Forge 的核心约束之一。
原因
- 避免 Service 层循环依赖导致 Spring 启动失败
- 保持 Plugin 的可插拔性(Plugin A 不应因为 Plugin B 不存在而无法启动)
- 确保职责清晰,跨 Plugin 逻辑上提到 Controller 层
错误示例
java
// ❌ 禁止:Plugin A 的 Service 注入 Plugin B 的 Service
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private CustomerService customerService; // 来自 Plugin B
public void createOrder(Order order) {
customerService.updateCustomer(order.getCustomerId());
}
}正确做法
java
// ✓ 正确:在 Controller 层协调多个 Service
@RestController
public class OrderController {
@Autowired
private OrderService orderService; // Plugin A
@Autowired
private CustomerService customerService; // Plugin B
@PostMapping("/order")
public RespInfo<Void> createOrder(@RequestBody Order order) {
orderService.createOrder(order);
customerService.updateCustomer(order.getCustomerId());
return RespInfo.success();
}
}事件驱动解耦
当 Plugin 之间需要协作但又不能直接注入时,使用事件机制:
java
// Plugin A 发送事件
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(Order order) {
save(order);
eventPublisher.publishEvent(new OrderCreatedEvent(order));
}
}
// Plugin B 监听事件
@Component
public class OrderEventListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 处理订单创建后的逻辑
}
}检查循环依赖
编译时检查
Maven 模块依赖关系在编译时检查。如果出现循环依赖,mvn clean install 会报错:
text
[ERROR] The projects in the reactor contain a cyclic reference运行时检查
Spring 启动时如果检测到 Bean 循环依赖,会抛出 BeanCurrentlyInCreationException。
排查方法
- 查看完整的异常堆栈
- 找到循环链路中的两个 Bean
- 将互相注入改为事件驱动或提取到上层
依赖管理 BOM
forge-dependencies 模块统一管理所有依赖版本:
xml
<!-- 在子模块中只需要引入依赖,不需要指定版本 -->
<dependency>
<groupId>com.mdframe.forge</groupId>
<artifactId>forge-starter-core</artifactId>
<!-- 版本由 BOM 统一管理 -->
</dependency>禁止在子模块中单独指定依赖版本,必须由 BOM 统一管理。
