aop

package
v1.53.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package aop 提供轻量级方法级切面(面向切面编程),对标 Spring AOP 的 @Before / @After / @Around,用于 Service 层:

  • 方法调用前后拦截(日志、耗时统计)
  • 前置校验(权限、参数),返回 error 终止调用
  • 环绕包装(事务、重试、熔断、上下文注入)

Web 层请使用 webiris 中间件(等同环绕切面:AccessLog/Auth/Limit/ErrorHandler)。 本包面向非 Web 场景(Service/Repository 方法)。

用法:

// 原始方法(任意签名)
getUser := func(ctx context.Context, id int64) (*User, error) { ... }

// 环绕切面:耗时 + 日志
getUser = aop.Around(getUser, func(ctx context.Context, params []interface{},
    next func() ([]interface{}, error)) ([]interface{}, error) {
    start := time.Now()
    results, err := next()
    log.Printf("GetUser cost=%s err=%v", time.Since(start), err)
    return results, err
}).(func(context.Context, int64) (*User, error))

// 前置校验:返回 error 终止调用
getUser = aop.Before(getUser, func(ctx context.Context, params []interface{}) error {
    if id := params[1].(int64); id <= 0 {
        return errors.New("invalid user id")
    }
    return nil
}).(func(context.Context, int64) (*User, error))

与 gbxioc 配合:将装饰后的 Service 结构注册进容器, 业务调用方无感知(接口签名不变)。

Index

Constants

This section is empty.

Variables

View Source
var ErrAborted = errors.New("aop: call aborted by before hook")

ErrAborted 由前置切面返回时,调用被终止的通用错误。

Functions

func After

func After(fn interface{}, hooks ...AfterHook) interface{}

After 为目标函数附加后置切面(记录日志/耗时/结果审计)。

func Around

func Around(fn interface{}, hook AroundHook) interface{}

Around 为目标函数附加环绕切面(事务/重试/熔断/耗时统计)。

func Before

func Before(fn interface{}, hooks ...BeforeHook) interface{}

Before 为目标函数附加前置切面,返回与原函数同签名的新函数(需类型断言使用)。 hook 返回 error 时终止调用,直接返回该错误(结果切片为空)。

Types

type AfterHook

type AfterHook func(ctx context.Context, params []interface{}, results []interface{}, err error)

AfterHook 后置切面:在目标方法返回后执行(无论成功失败)。

type AroundHook

type AroundHook func(ctx context.Context, params []interface{}, next func() ([]interface{}, error)) ([]interface{}, error)

AroundHook 环绕切面:包裹目标方法调用;调用 next() 执行目标方法。

type Aspect added in v1.19.0

type Aspect interface {
	// Name 切面名(日志/去重用)。
	Name() string
	// Before 前置拦截:可读/改 JoinPoint.Params;返回 error 终止调用。
	// 返回 ErrAborted 时调用被终止,不执行目标方法。
	Before(ctx context.Context, joinPoint *JoinPoint) error
	// After 后置回调:目标方法返回后执行(无论成功失败),
	// 可读取 JoinPoint.Results / Err / Cost。
	After(ctx context.Context, joinPoint *JoinPoint)
}

Aspect 面向切面接口(对标 Spring AOP @Aspect): 实现该接口即成为可接入的切面,业务 Service 通过 aop.Proxy 自动拦截。

type LogAspect struct{}
func (LogAspect) Name() string { return "log" }
func (LogAspect) Before(ctx context.Context, jp *aop.JoinPoint) error {
    log.Printf("call %s params=%v", jp.Method, jp.Params)
    return nil
}
func (LogAspect) After(ctx context.Context, jp *aop.JoinPoint) {
    log.Printf("call %s cost=%s err=%v", jp.Method, jp.Cost, jp.Err)
}

type BeforeHook

type BeforeHook func(ctx context.Context, params []interface{}) error

BeforeHook 前置切面:在目标方法调用前执行;返回 error 终止调用。

type Context

type Context struct {
	// Method 方法名(反射推断,无则空)。
	Method string
	// Params 调用参数(只读,修改不生效)。
	Params []interface{}
}

Context 携带调用信息。

type JoinPoint added in v1.19.0

type JoinPoint struct {
	// Method 被调用方法名(如 "GetUser")。
	Method string
	// Target 目标对象(Service 实现实例)。
	Target interface{}
	// Proxy 代理对象(调用方持有的引用)。
	Proxy interface{}
	// Params 调用参数;Before 中可修改(修改会传递给目标方法与后续切面)。
	Params []interface{}
	// Results 目标方法返回值(不含 error);After 中可读取。
	Results []interface{}
	// Err 目标方法返回的错误;Before 阶段为 nil。
	Err error
	// Start 调用开始时间。
	Start time.Time
	// Cost 调用耗时(After 中有效)。
	Cost time.Duration
}

JoinPoint 连接点上下文:切面中可获取/操作的全部调用信息。 与 Spring AOP 的 JoinPoint/ProceedingJoinPoint 对齐。

type Proxy added in v1.19.0

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy 是面向切面的方法调用执行器: 业务 Service 接口的代理实现通过 Invoke 触发切面链,目标方法由 next 闭包执行。

type UserService interface { GetUser(ctx context.Context, id int64) (*User, error) }

type userServiceProxy struct {
    inner *userServiceImpl
    aop   *aop.Proxy
}
func (p *userServiceProxy) GetUser(ctx context.Context, id int64) (*User, error) {
    var result *User
    _, err := p.aop.Invoke(ctx, "GetUser", []interface{}{ctx, id}, func() ([]interface{}, error) {
        var callErr error
        result, callErr = p.inner.GetUser(ctx, id)
        return []interface{}{result}, callErr
    })
    return result, err
}

func NewProxy added in v1.19.0

func NewProxy(target interface{}, aspects ...Aspect) *Proxy

NewProxy 创建代理执行器。 target 为目标对象(JoinPoint.Target);aspects 按注册顺序执行 (Before 顺序、After 逆序,洋葱模型,与 Spring 一致)。

func (*Proxy) AddAspects added in v1.19.0

func (p *Proxy) AddAspects(aspects ...Aspect)

AddAspects 运行时追加切面(热插拔切面)。

func (*Proxy) Invoke added in v1.19.0

func (p *Proxy) Invoke(ctx context.Context, method string, params []interface{}, next func() ([]interface{}, error)) ([]interface{}, error)

Invoke 执行切面链并调用目标方法。 method 为方法名;params 为调用参数;next 为目标方法闭包。 任一切面 Before 返回 error 时终止调用,next 不执行,直接返回该错误。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL