AOP概述
# 基本概念
RuleGo AOP(面向切面编程,Aspect Oriented Programming)机制,它类似拦截器或者hook机制,但是功能更加强大和灵活。
- 它允许在不修改规则链或节点的原有逻辑的情况下,对规则链的执行添加额外的行为,或者直接替换原规则链或者节点逻辑。
- 它允许把一些公共的行为(例如:日志、安全、规则链执行跟踪、组件降级、组件重试、组件缓存)从业务逻辑中分离出来。
AOP术语:
- 切入点(Pointcut): 是指被拦截的对象,框架提供一个方法,判断是否需要对该对象进行拦截。例如:某一些组件、某个组件ID、某个规则链ID、某种关系等。
- 通知/增强点(Advice): 增强点又称通知,是指在切入点位置,插入的额外逻辑代码,目前框架提供以下几种增强点:
- 节点前置通知/增强点(Before Advice):在节点OnMsg方法执行之前执行。
- 节点后置通知/增强点(After Advice):在节点OnMsg方法执行之后执行。
- 节点环绕通知/增强点(Around Advice):在节点OnMsg方法之前和之后执行。该类型增强点,可以替换原节点逻辑。可以实现节点故障转移、重试、缓存等功能。
- 开始通知/增强点(Start Advice):在执行规则引擎OnMsg方法执行之前执行。可以用于初始化一些数据。
- 结束通知/增强点(End Advice):在执行规则引擎OnMsg方法,分支链执行完成之后执行。
- 完成通知/增强点(Completed Advice):在执行规则引擎OnMsg方法,所有链执行完成之后执行。
- 创建通知/增强点(OnCreated Advice):在规则引擎创建完成之后执行。
- 重新加载通知/增强点(OnReload Advice):在规则引擎重新加载规则链或者节点配置执行完成之后执行。
- 销毁通知/增强点(OnDestroy Advice):在规则引擎销毁执行完成之后执行。
- 切面(Aspect): 切入点和增强点的集合。例如:Debug Aspect 它实现了Before Advice和After Advice。
- 框架内置部分切面,例如:Debug Aspect、Fallback Aspect。
- 你可以根据需要实现自定义切面。
# 用法
以下是一个拦截组件执行情况日志切面实现示例:
import (
"github.com/rulego/rulego/api/types"
)
//保护性检查,接口变动,在编译时中断
var (
_ types.BeforeAspect = (*Debug)(nil)
_ types.AfterAspect = (*Debug)(nil)
)
// Debug 节点debug日志切面
type Debug struct {
}
//值越小越优先执行
func (aspect *Debug) Order() int {
return 900
}
// PointCut 切入点 所有节点都会执行
func (aspect *Debug) PointCut(ctx types.RuleContext, msg types.RuleMsg, relationType string) bool {
return true
}
func (aspect *Debug) Before(ctx types.RuleContext, msg types.RuleMsg, relationType string) types.RuleMsg {
//异步记录In日志
aspect.onDebug(ctx, types.In, msg, relationType, nil)
return msg
}
func (aspect *Debug) After(ctx types.RuleContext, msg types.RuleMsg, err error, relationType string) types.RuleMsg {
//异步记录Out日志
aspect.onDebug(ctx, types.Out, msg, relationType, err)
return msg
}
func (aspect *Debug) onDebug(ctx types.RuleContext, flowType string, msg types.RuleMsg, relationType string, err error) {
ctx.SubmitTack(func () {
//异步记录日志
if ctx.Self() != nil && ctx.Self().IsDebugMode() {
var chainId = ""
if ctx.RuleChain() != nil {
chainId = ctx.RuleChain().GetNodeId().Id
}
ctx.Config().OnDebug(chainId, flowType, ctx.Self().GetNodeId().Id, msg.Copy(), relationType, err)
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
建议增加保护性检查,防止接口变动,在编译时可以检测出来。如:
var (
_ types.BeforeAspect = (*Debug)(nil)
_ types.AfterAspect = (*Debug)(nil)
)
1
2
3
4
2
3
4
然后创建规则链注册日志切面:
ruleEngine, err := rulego.New(chainId, ruleFile, types.WithAspects(&Debug{}))
1
在 GitHub 上编辑此页 (opens new window)
上次更新: 2024/10/23, 10:13:01