SpringBoot + 规则调用链分析 + 依赖拓扑图:自动识别规则间调用关系,避免循环依赖
前言
在企业级应用中,规则引擎是处理复杂业务逻辑的核心组件。随着业务的发展,规则数量不断增加,规则之间的调用关系也变得复杂。一个规则可能会调用多个其他规则,形成复杂的调用链。如果缺乏有效的管理和分析工具,很容易出现循环依赖、死循环等问题,导致系统崩溃或性能下降。
想象一下这样的场景:你的电商系统中有上百条业务规则,规则之间相互调用,形成复杂的依赖关系。当你需要修改某个规则时,不知道会影响哪些其他规则;当系统出现性能问题时,无法快速定位是哪条规则导致的循环调用。这不仅会增加开发和维护的难度,还会降低系统的稳定性和可靠性。
规则调用链分析和依赖拓扑图是解决这个问题的有效方案。通过自动识别规则间的调用关系,构建依赖拓扑图,可以可视化规则间的依赖关系,及时发现循环依赖和潜在问题。本文将详细介绍如何在 SpringBoot 项目中实现规则调用链分析和依赖拓扑图功能。
一、规则调用链分析的核心概念
1.1 什么是规则调用链
规则调用链是指在规则执行过程中,一个规则调用其他规则形成的调用序列。规则调用链可以反映规则之间的依赖关系和执行顺序,是分析规则行为的重要工具。
1.2 规则调用链分析的重要性
- 依赖管理:了解规则之间的依赖关系,便于规则管理和维护
- 性能优化:发现规则调用链中的性能瓶颈,优化规则执行效率
- 问题排查:快速定位规则执行过程中的问题,如循环依赖、死循环等
- 变更影响分析:在修改规则时,分析对其他规则的影响范围
- 架构优化:通过调用链分析,优化规则架构设计
1.3 常见的规则调用关系
| 调用类型 | 说明 | 示例 |
|---|---|---|
| 直接调用 | 规则 A 直接调用规则 B | 规则 A:if (age > 18) then invoke ruleB |
| 间接调用 | 规则 A 通过规则 C 调用规则 B | 规则 A → 规则 C → 规则 B |
| 条件调用 | 规则 A 在满足条件时调用规则 B | 规则 A:if (score > 60) then invoke ruleB |
| 循环调用 | 规则 A 调用规则 B,规则 B 又调用规则 A | 规则 A → 规则 B → 规则 A |
二、依赖拓扑图的核心概念
2.1 什么是依赖拓扑图
依赖拓扑图是一种图形化的表示方法,用于展示规则之间的依赖关系。在依赖拓扑图中,节点表示规则,边表示规则之间的调用关系。依赖拓扑图可以帮助我们直观地了解规则之间的依赖关系,发现潜在的问题。
2.2 依赖拓扑图的重要性
- 可视化依赖:直观展示规则之间的依赖关系,便于理解和管理
- 循环检测:快速发现规则之间的循环依赖,避免死循环
- 影响分析:分析规则变更对其他规则的影响范围
- 架构优化:通过拓扑图分析,优化规则架构设计
- 文档生成:自动生成规则依赖文档,便于团队协作
2.3 依赖拓扑图的表示方法
| 表示方法 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 有向图 | 使用有向边表示规则间的调用关系 | 直观,易于理解 | 复杂依赖关系下难以展示 |
| 树形图 | 以树形结构展示规则调用链 | 清晰展示调用层次 | 无法展示复杂依赖 |
| 矩阵图 | 使用矩阵表示规则间的依赖关系 | 适合大量规则 | 不够直观 |
| 层级图 | 按层级展示规则依赖关系 | 清晰展示依赖层次 | 无法展示跨层级依赖 |
三、SpringBoot 规则调用链分析实现
3.1 规则调用链追踪
3.1.1 规则调用上下文
@Data
public class RuleCallContext {
private String ruleId;
private String ruleName;
private String parentRuleId;
private int depth;
private long startTime;
private long endTime;
private Map<String, Object> inputData;
private Map<String, Object> outputData;
private List<RuleCallContext> childCalls = new ArrayList<>();
}
3.1.2 规则调用追踪服务
@Service
@Slf4j
public class RuleCallTraceService {
private final ThreadLocal<RuleCallContext> currentContext = new ThreadLocal<>();
public void startCall(String ruleId, String ruleName, Map<String, Object> inputData) {
RuleCallContext context = new RuleCallContext();
context.setRuleId(ruleId);
context.setRuleName(ruleName);
context.setInputData(inputData);
context.setDepth(getCurrentDepth());
context.setStartTime(System.currentTimeMillis());
RuleCallContext parentContext = currentContext.get();
if (parentContext != null) {
context.setParentRuleId(parentContext.getRuleId());
parentContext.getChildCalls().add(context);
}
currentContext.set(context);
log.info("Rule call started: {} (depth: {})", ruleName, context.getDepth());
}
public void endCall(Map<String, Object> outputData) {
RuleCallContext context = currentContext.get();
if (context != null) {
context.setEndTime(System.currentTimeMillis());
context.setOutputData(outputData);
log.info("Rule call ended: {} (duration: {}ms)",
context.getRuleName(),
context.getEndTime() - context.getStartTime());
currentContext.remove();
}
}
public RuleCallContext getCurrentContext() {
return currentContext.get();
}
private int getCurrentDepth() {
RuleCallContext context = currentContext.get();
return context != null ? context.getDepth() + 1 : 0;
}
}
3.2 规则依赖关系分析
3.2.1 规则依赖关系
@Data
public class RuleDependency {
private String sourceRuleId;
private String targetRuleId;
private String dependencyType; // DIRECT, INDIRECT, CONDITIONAL
private String condition;
}
3.2.2 规则依赖分析服务
@Service
@Slf4j
public class RuleDependencyAnalyzer {
private final Map<String, List<RuleDependency>> dependencyGraph = new ConcurrentHashMap<>();
public void analyzeDependencies(List<Rule> rules) {
dependencyGraph.clear();
for (Rule rule : rules) {
List<RuleDependency> dependencies = analyzeRuleDependencies(rule);
dependencyGraph.put(rule.getId(), dependencies);
}
log.info("Analyzed dependencies for {} rules", rules.size());
}
private List<RuleDependency> analyzeRuleDependencies(Rule rule) {
List<RuleDependency> dependencies = new ArrayList<>();
// 解析规则表达式,查找调用其他规则的地方
List<String> calledRules = extractCalledRules(rule.getExpression());
for (String calledRuleId : calledRules) {
RuleDependency dependency = new RuleDependency();
dependency.setSourceRuleId(rule.getId());
dependency.setTargetRuleId(calledRuleId);
dependency.setDependencyType("DIRECT");
dependencies.add(dependency);
}
return dependencies;
}
private List<String> extractCalledRules(String expression) {
List<String> calledRules = new ArrayList<>();
// 使用正则表达式提取规则调用
Pattern pattern = Pattern.compile("invoke\\s*\\(\\s*['\"]([^'\"]+)['\"]");
Matcher matcher = pattern.matcher(expression);
while (matcher.find()) {
calledRules.add(matcher.group(1));
}
return calledRules;
}
public List<RuleDependency> getDependencies(String ruleId) {
return dependencyGraph.getOrDefault(ruleId, Collections.emptyList());
}
public Map<String, List<RuleDependency>> getDependencyGraph() {
return dependencyGraph;
}
}
四、依赖拓扑图实现
4.1 循环依赖检测
4.1.1 循环依赖检测服务
@Service
@Slf4j
public class CircularDependencyDetector {
@Autowired
private RuleDependencyAnalyzer dependencyAnalyzer;
public List<List<String>> detectCircularDependencies() {
Map<String, List<RuleDependency>> dependencyGraph = dependencyAnalyzer.getDependencyGraph();
List<List<String>> circularPaths = new ArrayList<>();
for (String ruleId : dependencyGraph.keySet()) {
detectCycle(ruleId, ruleId, new ArrayList<>(), circularPaths, dependencyGraph);
}
if (!circularPaths.isEmpty()) {
log.error("Detected {} circular dependencies", circularPaths.size());
}
return circularPaths;
}
private void detectCycle(String startRuleId, String currentRuleId, List<String> path,
List<List<String>> circularPaths,
Map<String, List<RuleDependency>> dependencyGraph) {
path.add(currentRuleId);
List<RuleDependency> dependencies = dependencyGraph.get(currentRuleId);
if (dependencies != null) {
for (RuleDependency dependency : dependencies) {
String targetRuleId = dependency.getTargetRuleId();
if (targetRuleId.equals(startRuleId)) {
// 发现循环
List<String> cycle = new ArrayList<>(path);
cycle.add(targetRuleId);
circularPaths.add(cycle);
} else if (!path.contains(targetRuleId)) {
// 继续搜索
detectCycle(startRuleId, targetRuleId, new ArrayList<>(path),
circularPaths, dependencyGraph);
}
}
}
}
}
4.2 拓扑图生成
4.2.1 拓扑图生成服务
@Service
@Slf4j
public class TopologyGraphGenerator {
@Autowired
private RuleDependencyAnalyzer dependencyAnalyzer;
public String generateGraphvizGraph() {
Map<String, List<RuleDependency>> dependencyGraph = dependencyAnalyzer.getDependencyGraph();
StringBuilder graph = new StringBuilder();
graph.append("digraph RuleDependencies {\n");
graph.append(" rankdir=LR;\n");
graph.append(" node [shape=box];\n\n");
for (Map.Entry<String, List<RuleDependency>> entry : dependencyGraph.entrySet()) {
String sourceRuleId = entry.getKey();
for (RuleDependency dependency : entry.getValue()) {
String targetRuleId = dependency.getTargetRuleId();
graph.append(String.format(" \"%s\" -> \"%s\";\n", sourceRuleId, targetRuleId));
}
}
graph.append("}\n");
return graph.toString();
}
public String generateMermaidGraph() {
Map<String, List<RuleDependency>> dependencyGraph = dependencyAnalyzer.getDependencyGraph();
StringBuilder graph = new StringBuilder();
graph.append("graph TD\n");
for (Map.Entry<String, List<RuleDependency>> entry : dependencyGraph.entrySet()) {
String sourceRuleId = entry.getKey();
for (RuleDependency dependency : entry.getValue()) {
String targetRuleId = dependency.getTargetRuleId();
graph.append(String.format(" %s --> %s\n", sourceRuleId, targetRuleId));
}
}
return graph.toString();
}
}
五、SpringBoot 完整实现
5.1 项目依赖
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 规则引擎 -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.69.0.Final</version>
</dependency>
<!-- 序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Spring Boot Configuration Processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
5.2 配置文件
server:
port: 8080
spring:
application:
name: rule-dependency-analyzer-demo
# 规则依赖分析配置
rule:
dependency:
analyzer:
enabled: true
max-depth: 10
detect-circular: true
# 规则示例
rules:
- id: rule1
name: 年龄验证规则
expression: "age >= 18 && age <= 60"
description: 验证用户年龄是否在合法范围内
- id: rule2
name: 分数验证规则
expression: "score >= 0 && score <= 100"
description: 验证分数是否在合法范围内
- id: rule3
name: 综合验证规则
expression: "invoke('rule1') && invoke('rule2')"
description: 综合验证年龄和分数
- id: rule4
name: 循环规则A
expression: "invoke('rule5')"
description: 循环规则A
- id: rule5
name: 循环规则B
expression: "invoke('rule4')"
description: 循环规则B
5.3 核心配置类
5.3.1 规则依赖分析配置
@Data
@ConfigurationProperties(prefix = "rule.dependency.analyzer")
public class RuleDependencyAnalyzerProperties {
private boolean enabled = true;
private int maxDepth = 10;
private boolean detectCircular = true;
}
5.4 服务实现
5.4.1 规则调用追踪服务
@Service
@Slf4j
public class RuleCallTraceService {
private final ThreadLocal<RuleCallContext> currentContext = new ThreadLocal<>();
public void startCall(String ruleId, String ruleName, Map<String, Object> inputData) {
RuleCallContext context = new RuleCallContext();
context.setRuleId(ruleId);
context.setRuleName(ruleName);
context.setInputData(inputData);
context.setDepth(getCurrentDepth());
context.setStartTime(System.currentTimeMillis());
RuleCallContext parentContext = currentContext.get();
if (parentContext != null) {
context.setParentRuleId(parentContext.getRuleId());
parentContext.getChildCalls().add(context);
}
currentContext.set(context);
log.info("Rule call started: {} (depth: {})", ruleName, context.getDepth());
}
public void endCall(Map<String, Object> outputData) {
RuleCallContext context = currentContext.get();
if (context != null) {
context.setEndTime(System.currentTimeMillis());
context.setOutputData(outputData);
log.info("Rule call ended: {} (duration: {}ms)",
context.getRuleName(),
context.getEndTime() - context.getStartTime());
currentContext.remove();
}
}
public RuleCallContext getCurrentContext() {
return currentContext.get();
}
private int getCurrentDepth() {
RuleCallContext context = currentContext.get();
return context != null ? context.getDepth() + 1 : 0;
}
@Data
public static class RuleCallContext {
private String ruleId;
private String ruleName;
private String parentRuleId;
private int depth;
private long startTime;
private long endTime;
private Map<String, Object> inputData;
private Map<String, Object> outputData;
private List<RuleCallContext> childCalls = new ArrayList<>();
}
}
5.4.2 规则依赖分析服务
@Service
@Slf4j
public class RuleDependencyAnalyzer {
private final Map<String, List<RuleDependency>> dependencyGraph = new ConcurrentHashMap<>();
public void analyzeDependencies(List<Rule> rules) {
dependencyGraph.clear();
for (Rule rule : rules) {
List<RuleDependency> dependencies = analyzeRuleDependencies(rule);
dependencyGraph.put(rule.getId(), dependencies);
}
log.info("Analyzed dependencies for {} rules", rules.size());
}
private List<RuleDependency> analyzeRuleDependencies(Rule rule) {
List<RuleDependency> dependencies = new ArrayList<>();
// 解析规则表达式,查找调用其他规则的地方
List<String> calledRules = extractCalledRules(rule.getExpression());
for (String calledRuleId : calledRules) {
RuleDependency dependency = new RuleDependency();
dependency.setSourceRuleId(rule.getId());
dependency.setTargetRuleId(calledRuleId);
dependency.setDependencyType("DIRECT");
dependencies.add(dependency);
}
return dependencies;
}
private List<String> extractCalledRules(String expression) {
List<String> calledRules = new ArrayList<>();
// 使用正则表达式提取规则调用
Pattern pattern = Pattern.compile("invoke\\s*\\(\\s*['\"]([^'\"]+)['\"]");
Matcher matcher = pattern.matcher(expression);
while (matcher.find()) {
calledRules.add(matcher.group(1));
}
return calledRules;
}
public List<RuleDependency> getDependencies(String ruleId) {
return dependencyGraph.getOrDefault(ruleId, Collections.emptyList());
}
public Map<String, List<RuleDependency>> getDependencyGraph() {
return dependencyGraph;
}
@Data
public static class Rule {
private String id;
private String name;
private String expression;
private String description;
}
@Data
public static class RuleDependency {
private String sourceRuleId;
private String targetRuleId;
private String dependencyType;
private String condition;
}
}
5.4.3 循环依赖检测服务
@Service
@Slf4j
public class CircularDependencyDetector {
@Autowired
private RuleDependencyAnalyzer dependencyAnalyzer;
public List<List<String>> detectCircularDependencies() {
Map<String, List<RuleDependencyAnalyzer.RuleDependency>> dependencyGraph =
dependencyAnalyzer.getDependencyGraph();
List<List<String>> circularPaths = new ArrayList<>();
for (String ruleId : dependencyGraph.keySet()) {
detectCycle(ruleId, ruleId, new ArrayList<>(), circularPaths, dependencyGraph);
}
if (!circularPaths.isEmpty()) {
log.error("Detected {} circular dependencies", circularPaths.size());
}
return circularPaths;
}
private void detectCycle(String startRuleId, String currentRuleId, List<String> path,
List<List<String>> circularPaths,
Map<String, List<RuleDependencyAnalyzer.RuleDependency>> dependencyGraph) {
path.add(currentRuleId);
List<RuleDependencyAnalyzer.RuleDependency> dependencies = dependencyGraph.get(currentRuleId);
if (dependencies != null) {
for (RuleDependencyAnalyzer.RuleDependency dependency : dependencies) {
String targetRuleId = dependency.getTargetRuleId();
if (targetRuleId.equals(startRuleId)) {
// 发现循环
List<String> cycle = new ArrayList<>(path);
cycle.add(targetRuleId);
circularPaths.add(cycle);
} else if (!path.contains(targetRuleId)) {
// 继续搜索
detectCycle(startRuleId, targetRuleId, new ArrayList<>(path),
circularPaths, dependencyGraph);
}
}
}
}
}
5.4.4 拓扑图生成服务
@Service
@Slf4j
public class TopologyGraphGenerator {
@Autowired
private RuleDependencyAnalyzer dependencyAnalyzer;
public String generateGraphvizGraph() {
Map<String, List<RuleDependencyAnalyzer.RuleDependency>> dependencyGraph =
dependencyAnalyzer.getDependencyGraph();
StringBuilder graph = new StringBuilder();
graph.append("digraph RuleDependencies {\n");
graph.append(" rankdir=LR;\n");
graph.append(" node [shape=box];\n\n");
for (Map.Entry<String, List<RuleDependencyAnalyzer.RuleDependency>> entry : dependencyGraph.entrySet()) {
String sourceRuleId = entry.getKey();
for (RuleDependencyAnalyzer.RuleDependency dependency : entry.getValue()) {
String targetRuleId = dependency.getTargetRuleId();
graph.append(String.format(" \"%s\" -> \"%s\";\n", sourceRuleId, targetRuleId));
}
}
graph.append("}\n");
return graph.toString();
}
public String generateMermaidGraph() {
Map<String, List<RuleDependencyAnalyzer.RuleDependency>> dependencyGraph =
dependencyAnalyzer.getDependencyGraph();
StringBuilder graph = new StringBuilder();
graph.append("graph TD\n");
for (Map.Entry<String, List<RuleDependencyAnalyzer.RuleDependency>> entry : dependencyGraph.entrySet()) {
String sourceRuleId = entry.getKey();
for (RuleDependencyAnalyzer.RuleDependency dependency : entry.getValue()) {
String targetRuleId = dependency.getTargetRuleId();
graph.append(String.format(" %s --> %s\n", sourceRuleId, targetRuleId));
}
}
return graph.toString();
}
}
5.5 控制器
5.5.1 规则依赖分析控制器
@RestController
@RequestMapping("/api/rule")
@Slf4j
public class RuleDependencyController {
@Autowired
private RuleDependencyAnalyzer dependencyAnalyzer;
@Autowired
private CircularDependencyDetector circularDetector;
@Autowired
private TopologyGraphGenerator graphGenerator;
@Autowired
private RuleCallTraceService traceService;
@PostMapping("/analyze")
public Map<String, Object> analyzeDependencies(@RequestBody List<RuleDependencyAnalyzer.Rule> rules) {
dependencyAnalyzer.analyzeDependencies(rules);
Map<String, Object> result = new HashMap<>();
result.put("dependencyGraph", dependencyAnalyzer.getDependencyGraph());
result.put("circularDependencies", circularDetector.detectCircularDependencies());
return result;
}
@GetMapping("/dependencies/{ruleId}")
public List<RuleDependencyAnalyzer.RuleDependency> getDependencies(@PathVariable String ruleId) {
return dependencyAnalyzer.getDependencies(ruleId);
}
@GetMapping("/graph/graphviz")
public String generateGraphvizGraph() {
return graphGenerator.generateGraphvizGraph();
}
@GetMapping("/graph/mermaid")
public String generateMermaidGraph() {
return graphGenerator.generateMermaidGraph();
}
@GetMapping("/trace/current")
public RuleCallTraceService.RuleCallContext getCurrentTrace() {
return traceService.getCurrentContext();
}
}
六、最佳实践
6.1 规则调用链管理
原则:
- 控制调用深度:限制规则调用的最大深度,避免无限递归
- 记录调用链:记录完整的调用链,便于问题排查
- 性能监控:监控规则调用的性能,及时发现性能问题
- 错误处理:在规则调用失败时,提供详细的错误信息
建议:
- 设置规则调用的最大深度,默认为 10 层
- 记录规则调用的输入输出,便于调试
- 监控规则调用的执行时间,设置超时阈值
- 提供规则调用的可视化界面,便于分析
6.2 循环依赖预防
原则:
- 静态检测:在规则部署前进行循环依赖检测
- 动态检测:在规则执行时检测循环依赖
- 自动修复:提供自动修复循环依赖的建议
- 告警机制:发现循环依赖时及时告警
建议:
- 在规则部署前强制进行循环依赖检测
- 在规则执行时设置最大调用次数,防止死循环
- 提供循环依赖的自动修复建议
- 建立循环依赖的告警机制,及时通知开发人员
6.3 依赖拓扑图使用
原则:
- 定期更新:定期更新依赖拓扑图,反映最新的依赖关系
- 可视化展示:使用图形化工具展示依赖拓扑图
- 交互式分析:提供交互式分析功能,便于深入分析
- 文档生成:自动生成依赖文档,便于团队协作
建议:
- 每次规则变更后自动更新依赖拓扑图
- 使用 Graphviz 或 Mermaid 等工具生成可视化图表
- 提供依赖拓扑图的交互式分析功能
- 自动生成规则依赖文档,便于团队协作
6.4 性能优化
原则:
- 缓存机制:缓存依赖分析结果,避免重复计算
- 增量更新:规则变更时只更新受影响的依赖关系
- 异步处理:依赖分析采用异步方式,不影响系统性能
- 采样策略:对高频执行的规则采用采样分析策略
建议:
- 使用缓存技术存储依赖分析结果
- 规则变更时只更新受影响的依赖关系
- 使用消息队列处理依赖分析的异步任务
- 对高频执行的规则设置采样率
七、总结
规则调用链分析和依赖拓扑图是管理复杂规则系统的有效工具。通过自动识别规则间的调用关系,构建依赖拓扑图,可以可视化规则间的依赖关系,及时发现循环依赖和潜在问题。在实际项目中,我们应该根据业务需求和系统特点,合理配置规则调用链分析和依赖拓扑图功能,建立规则管理的标准化流程,提高团队的开发和维护效率。通过规则调用链分析和依赖拓扑图功能,可以快速发现和解决规则依赖问题,提高系统的稳定性和可靠性。
互动话题:
- 你的项目中是如何管理规则依赖关系的?
- 你认为规则调用链分析最大的挑战是什么?
- 你有使用过依赖拓扑图来分析规则依赖吗?
欢迎在评论区留言讨论!更多技术文章,欢迎关注公众号:服务端技术精选
标题:SpringBoot + 规则调用链分析 + 依赖拓扑图:自动识别规则间调用关系,避免循环依赖
作者:jiangyi
地址:http://jiangyi.space/articles/2026/04/05/1774792787244.html
公众号:服务端技术精选
- 前言
- 一、规则调用链分析的核心概念
- 1.1 什么是规则调用链
- 1.2 规则调用链分析的重要性
- 1.3 常见的规则调用关系
- 二、依赖拓扑图的核心概念
- 2.1 什么是依赖拓扑图
- 2.2 依赖拓扑图的重要性
- 2.3 依赖拓扑图的表示方法
- 三、SpringBoot 规则调用链分析实现
- 3.1 规则调用链追踪
- 3.1.1 规则调用上下文
- 3.1.2 规则调用追踪服务
- 3.2 规则依赖关系分析
- 3.2.1 规则依赖关系
- 3.2.2 规则依赖分析服务
- 四、依赖拓扑图实现
- 4.1 循环依赖检测
- 4.1.1 循环依赖检测服务
- 4.2 拓扑图生成
- 4.2.1 拓扑图生成服务
- 五、SpringBoot 完整实现
- 5.1 项目依赖
- 5.2 配置文件
- 5.3 核心配置类
- 5.3.1 规则依赖分析配置
- 5.4 服务实现
- 5.4.1 规则调用追踪服务
- 5.4.2 规则依赖分析服务
- 5.4.3 循环依赖检测服务
- 5.4.4 拓扑图生成服务
- 5.5 控制器
- 5.5.1 规则依赖分析控制器
- 六、最佳实践
- 6.1 规则调用链管理
- 6.2 循环依赖预防
- 6.3 依赖拓扑图使用
- 6.4 性能优化
- 七、总结
评论