AOP Overview
# Basic Concepts
RuleGo AOP (Aspect Oriented Programming) mechanism ,which is similar to interceptor or hook mechanism, but more powerful and flexible.
- It allows adding extra behavior to the rule chain execution without modifying the original logic of the rule chain or nodes.
- It allows separating some common behaviors (such as logging, security, rule chain execution tracking, component degradation, component retry, component caching) from the business logic.
AOP terminology:
- Pointcut: is the object to be intercepted, the framework provides a method to determine whether to intercept the object. For example: specify some component types or relationType to execute the aspect logic;return ctx.Self().Type()=="mqttClient".
- Advice: also known as enhancement point, is the extra logic code inserted at the pointcut position, the framework currently provides the following types of advice:
- Node before advice (Before Advice): executes before the node OnMsg method.
- Node after advice (After Advice): executes after the node OnMsg method.
- Node Around advice (Around Advice): executes before and after the node OnMsg method. This type of advice can replace the original node logic. It can implement node failover, retry, caching and other functions.
- Start advice (Start Advice): executes before the rule engine OnMsg method. It can be used to initialize some data.
- End advice (End Advice): executes after the rule engine OnMsg method and the branch chain execution ends.
- Completed advice (Completed Advice): executes after the rule engine OnMsg method and all branch chain execution ends.
- OnCreated advice (OnCreated Advice): executes after the rule engine is successfully created.
- OnReload advice (OnReload Advice): executes after the rule engine reloads the rule chain or node configuration.
- OnDestroy advice (OnDestroy Advice): executes after the rule engine instance is destroyed.
- Aspect: is the collection of pointcuts and advice. For example: Debug Aspect It implements Before Advice and After Advice.
- The framework has some built-in aspects, such as: Debug Aspect, Fallback Aspect.
- You can customize the aspect.
# Usage
The following is an example of a debug log aspect implementation that intercepts the component execution situation:
import (
"github.com/rulego/rulego/api/types"
)
var (
// Compile-time check Debug implements types.BeforeAspect.
_ types.BeforeAspect = (*Debug)(nil)
// Compile-time check Debug implements types.AfterAspect.
_ types.AfterAspect = (*Debug)(nil)
)
// Debug node debug log aspect
type Debug struct {
}
//The smaller the value, the higher the execution priority
func (aspect *Debug) Order() int {
return 900
}
// PointCut pointcut all nodes will execute
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 {
//Asynchronously record In log
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 {
//Asynchronously record Out log
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 () {
//Asynchronously record log
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
50
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
50
It is recommended to add protection checks to prevent interface changes that can be detected at compile time. For example:
var (
_ types.BeforeAspect = (*Debug)(nil)
_ types.AfterAspect = (*Debug)(nil)
)
1
2
3
4
2
3
4
Then register the log aspect in create RuleEngine:
ruleEngine, err := rulego.New(chainId, ruleFile, types.WithAspects(&Debug{}))
1
Edit this page on GitHub (opens new window)
Last Updated: 2024/10/31, 11:56:12