高性能IoC(控制反转)容器设计与Aop(面向切面编程)三:狠狠地“织入”(面向切面编程)

第三部分:设计篇 - AOP 框架架构设计

在第二部分中,我们完成了 IoC 容器的设计。现在,让我们设计 AOP 框架,实现面向切面编程的能力。


第6章:AOP 核心架构

6.1 整体架构设计

AOP 框架的核心组件:

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        AOP 框架架构                             │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                         切面定义层                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │   @Aspect   │  │   @Before   │  │   @Around   │             │
│  │  切面标记   │  │  前置通知   │  │  环绕通知   │             │
│  └─────────────┘  └─────────────┘  └─────────────┘             │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         切面解析层                              │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    AspectParser                          │   │
│  │  解析 @Aspect 类,生成 MethodInterceptor 列表            │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         拦截器层                                │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │ BeforeAdv   │  │ AroundAdv   │  │ AfterAdv    │             │
│  │ Interceptor │  │ Interceptor │  │ Interceptor │             │
│  └─────────────┘  └─────────────┘  └─────────────┘             │
│                          │                                      │
│                          ▼                                      │
│              ┌───────────────────────┐                          │
│              │   InterceptorChain    │                          │
│              │      拦截器链         │                          │
│              └───────────────────────┘                          │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         代理层                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                   AopProxyFactory                        │   │
│  │  使用 ByteBuddy 创建动态代理                             │   │
│  └─────────────────────────────────────────────────────────┘   │
│                          │                                      │
│          ┌───────────────┼───────────────┐                      │
│          ▼               ▼               ▼                      │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐               │
│  │  普通类代理 │ │ 接口代理    │ │Kotlin Object│               │
│  │             │ │             │ │   代理      │               │
│  └─────────────┘ └─────────────┘ └─────────────┘               │
└─────────────────────────────────────────────────────────────────┘

与Spring使用的CGLib不同,我们使用更为现代的ByteBuddy创建动态代理,支持final class,而且性能更优

核心组件职责

组件 职责
切面注解 定义切面、通知类型、切入点
AspectParser 解析切面类,生成拦截器
PointcutMatcher 判断方法是否匹配切入点
MethodInterceptor 方法拦截器,执行通知逻辑
InterceptorChain 管理拦截器链的执行顺序
AopProxyFactory 创建动态代理对象

6.2 切面注解设计

切面标记注解

kotlin 复制代码
/**
 * 标记一个类为切面
 *
 * @param order 切面优先级,数值越小优先级越高
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Aspect(
    val order: Int = Int.MAX_VALUE
)

通知注解设计

kotlin 复制代码
/**
 * 前置通知
 * 在目标方法执行前执行
 *
 * @param value 要匹配的注解类型(混淆安全)
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Before(
    vararg val value: KClass<out Annotation>
)

/**
 * 后置通知
 * 在目标方法执行后执行(无论是否异常)
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class After(
    vararg val value: KClass<out Annotation>
)

/**
 * 环绕通知
 * 包裹目标方法,可以控制是否执行
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Around(
    vararg val value: KClass<out Annotation>
)

/**
 * 返回通知
 * 在目标方法正常返回后执行
 *
 * @param returning 用于接收返回值的参数名
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class AfterReturning(
    vararg val value: KClass<out Annotation>,
    val returning: String = "result"
)

/**
 * 异常通知
 * 在目标方法抛出异常后执行
 *
 * @param throwing 用于接收异常的参数名
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class AfterThrowing(
    vararg val value: KClass<out Annotation>,
    val throwing: String = "ex"
)

6.3 混淆安全的切入点设计

为什么字符串表达式不安全?

传统的 AOP 框架(如 Spring AOP)使用字符串表达式定义切入点:

kotlin 复制代码
// Spring 风格(不安全!)
@Around("execution(* com.example.service.*.*(..))")
fun logAround(pjp: ProceedingJoinPoint): Any? { ... }

@Around("@annotation(com.example.Cacheable)")
fun handleCache(pjp: ProceedingJoinPoint): Any? { ... }

问题:当代码被混淆后:

  • com.example.service.PlayerService 可能变成 a.b.c
  • com.example.Cacheable 可能变成 a.b.d

字符串表达式无法跟随混淆变化,导致切面失效!

我们的解决方案:KClass 引用

kotlin 复制代码
// 我们的方式(混淆安全!)
@Around(Cacheable::class)
fun handleCache(pjp: ProceedingJoinPoint): Any? { ... }

@Before(Loggable::class, Monitored::class)  // 支持多个注解
fun logBefore(joinPoint: JoinPoint) { ... }

为什么安全?

  • Cacheable::class 是类型引用,不是字符串
  • 混淆器会同时修改引用和被引用的类
  • 运行时通过 Class 对象匹配,不依赖名称

切入点匹配器设计

kotlin 复制代码
/**
 * 切入点匹配器接口
 */
interface PointcutMatcher {

    /**
     * 检查类是否可能匹配(快速过滤)
     */
    fun matchesClass(targetClass: Class<*>): Boolean = true

    /**
     * 检查方法是否匹配
     */
    fun matches(targetClass: Class<*>, method: Method): Boolean

    companion object {
        /**
         * 从注解数组创建匹配器
         */
        fun fromAnnotations(
            annotations: Array<out KClass<out Annotation>>,
            checkClass: Boolean = false
        ): PointcutMatcher {
            if (annotations.isEmpty()) return NeverMatchPointcutMatcher
            if (annotations.size == 1) {
                return AnnotationPointcutMatcher(annotations[0].java, checkClass)
            }
            return CompositeOrPointcutMatcher(
                annotations.map { AnnotationPointcutMatcher(it.java, checkClass) }
            )
        }
    }
}

/**
 * 永不匹配的匹配器
 */
object NeverMatchPointcutMatcher : PointcutMatcher {
    override fun matches(targetClass: Class<*>, method: Method) = false
}

/**
 * 注解匹配器
 * 匹配带有指定注解的方法
 */
class AnnotationPointcutMatcher(
    private val annotationClass: Class<out Annotation>,
    private val checkClass: Boolean = false
) : PointcutMatcher {

    override fun matchesClass(targetClass: Class<*>): Boolean {
        if (!checkClass) return true
        return targetClass.isAnnotationPresent(annotationClass)
    }

    override fun matches(targetClass: Class<*>, method: Method): Boolean {
        // 检查方法上是否有该注解
        if (method.isAnnotationPresent(annotationClass)) {
            return true
        }

        // 如果需要检查类级别注解
        if (checkClass && targetClass.isAnnotationPresent(annotationClass)) {
            return true
        }

        return false
    }
}

/**
 * 组合匹配器(OR 逻辑)
 * 任意一个子匹配器匹配即可
 */
class CompositeOrPointcutMatcher(
    private val matchers: List<PointcutMatcher>
) : PointcutMatcher {

    override fun matchesClass(targetClass: Class<*>): Boolean {
        return matchers.any { it.matchesClass(targetClass) }
    }

    override fun matches(targetClass: Class<*>, method: Method): Boolean {
        return matchers.any { it.matches(targetClass, method) }
    }
}

使用示例

kotlin 复制代码
// 定义业务注解
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Cacheable(
    val value: String,
    val key: String = ""
)

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Loggable

// 定义切面
@Aspect(order = 100)
object CacheAspect {

    @Around(Cacheable::class)  // 匹配所有 @Cacheable 方法
    fun handleCache(pjp: ProceedingJoinPoint): Any? {
        val annotation = pjp.getAnnotation(Cacheable::class.java)
            ?: return pjp.proceed()

        val cacheName = annotation.value
        val key = parseKey(annotation.key, pjp.args)

        // 尝试从缓存获取
        val cached = CacheManager.get(cacheName, key)
        if (cached != null) return cached

        // 执行方法并缓存结果
        val result = pjp.proceed()
        CacheManager.put(cacheName, key, result)
        return result
    }
}

@Aspect(order = 1)
object LoggingAspect {

    @Before(Loggable::class)
    fun logBefore(joinPoint: JoinPoint) {
        println("调用方法: ${joinPoint.method.name}")
    }
}

// 使用切面
@Service
class PlayerService {

    @Loggable
    @Cacheable("players", key = "#p0")
    fun getPlayer(uuid: String): PlayerData? {
        // 这个方法会被 LoggingAspect 和 CacheAspect 拦截
        return database.query(uuid)
    }
}

第7章:JoinPoint 与 ProceedingJoinPoint

JoinPoint 是 AOP 中非常重要的概念,它封装了连接点的所有信息,让通知方法能够访问目标方法的上下文。

7.1 JoinPoint 设计

接口定义

kotlin 复制代码
/**
 * 连接点
 * 封装了目标方法执行时的上下文信息
 */
interface JoinPoint {

    /** 目标对象(被代理的原始对象) */
    val target: Any

    /** 代理对象 */
    val proxy: Any

    /** 目标方法 */
    val method: Method

    /** 方法参数 */
    val args: Array<Any?>

    /** 目标类 */
    val targetClass: Class<*>
        get() = target::class.java

    /**
     * 获取方法上的注解
     */
    fun <T : Annotation> getAnnotation(annotationClass: Class<T>): T?

    /**
     * 检查方法是否有指定注解
     */
    fun hasAnnotation(annotationClass: Class<out Annotation>): Boolean

    /**
     * 获取方法签名字符串
     */
    fun getSignature(): String
}

实现类

kotlin 复制代码
/**
 * JoinPoint 默认实现
 */
open class DefaultJoinPoint(
    override val target: Any,
    override val proxy: Any,
    override val method: Method,
    override val args: Array<Any?>
) : JoinPoint {

    /** 注解缓存,避免重复反射 */
    private val annotationCache = mutableMapOf<Class<*>, Annotation?>()

    override fun <T : Annotation> getAnnotation(annotationClass: Class<T>): T? {
        @Suppress("UNCHECKED_CAST")
        return annotationCache.getOrPut(annotationClass) {
            method.getAnnotation(annotationClass)
        } as? T
    }

    override fun hasAnnotation(annotationClass: Class<out Annotation>): Boolean {
        return getAnnotation(annotationClass) != null
    }

    override fun getSignature(): String {
        val params = method.parameterTypes.joinToString(", ") { it.simpleName }
        return "${targetClass.simpleName}.${method.name}($params)"
    }

    override fun toString(): String {
        return "JoinPoint(${getSignature()})"
    }
}

7.2 ProceedingJoinPoint 设计

ProceedingJoinPointJoinPoint 的扩展,专门用于 @Around 通知。它提供了 proceed() 方法来执行目标方法。

接口定义

kotlin 复制代码
/**
 * 可执行的连接点
 * 用于 @Around 通知,可以控制目标方法的执行
 */
interface ProceedingJoinPoint : JoinPoint {

    /**
     * 执行目标方法(使用原始参数)
     *
     * @return 目标方法的返回值
     */
    fun proceed(): Any?

    /**
     * 执行目标方法(使用新参数)
     *
     * @param args 新的参数数组
     * @return 目标方法的返回值
     */
    fun proceed(args: Array<Any?>): Any?
}

实现类

kotlin 复制代码
/**
 * ProceedingJoinPoint 默认实现
 */
class DefaultProceedingJoinPoint(
    target: Any,
    proxy: Any,
    method: Method,
    args: Array<Any?>,
    private val methodHandle: MethodHandle,
    private val interceptorChain: InterceptorChain
) : DefaultJoinPoint(target, proxy, method, args), ProceedingJoinPoint {

    /** 当前参数(可能被修改) */
    private var currentArgs: Array<Any?> = args

    /** 是否已经执行过 */
    private var proceeded = false

    override fun proceed(): Any? {
        return proceed(currentArgs)
    }

    override fun proceed(args: Array<Any?>): Any? {
        this.currentArgs = args

        // 继续执行拦截器链
        return interceptorChain.proceed(
            DefaultProceedingJoinPoint(
                target, proxy, method, args, methodHandle, interceptorChain
            )
        )
    }

    /**
     * 执行目标方法(由拦截器链最终调用)
     */
    internal fun invokeTarget(): Any? {
        if (proceeded) {
            throw IllegalStateException("proceed() 已经被调用过")
        }
        proceeded = true

        return try {
            // 使用Java7+新增的 MethodHandle 调用目标方法(高性能)
            if (currentArgs.isEmpty()) {
                methodHandle.invoke(target)
            } else {
                methodHandle.invokeWithArguments(listOf(target) + currentArgs)
            }
        } catch (e: Throwable) {
            // 解包 InvocationTargetException
            throw if (e is java.lang.reflect.InvocationTargetException) {
                e.targetException
            } else {
                e
            }
        }
    }
}

使用示例

kotlin 复制代码
@Aspect
object TimingAspect {

    @Around(Timed::class)
    fun measureTime(pjp: ProceedingJoinPoint): Any? {
        val startTime = System.nanoTime()

        try {
            // 执行目标方法
            return pjp.proceed()
        } finally {
            val duration = System.nanoTime() - startTime
            println("${pjp.getSignature()} 执行耗时: ${duration / 1_000_000}ms")
        }
    }
}

@Aspect
object RetryAspect {

    @Around(Retryable::class)
    fun retry(pjp: ProceedingJoinPoint): Any? {
        val annotation = pjp.getAnnotation(Retryable::class.java)!!
        val maxRetries = annotation.maxRetries

        var lastException: Throwable? = null

        repeat(maxRetries) { attempt ->
            try {
                return pjp.proceed()
            } catch (e: Throwable) {
                lastException = e
                println("第 ${attempt + 1} 次重试失败: ${e.message}")
            }
        }

        throw lastException!!
    }
}

@Aspect
object ParameterModifyAspect {

    @Around(Trimmed::class)
    fun trimStringParams(pjp: ProceedingJoinPoint): Any? {
        // 修改参数:将所有字符串参数去除首尾空格
        val trimmedArgs = pjp.args.map { arg ->
            if (arg is String) arg.trim() else arg
        }.toTypedArray()

        // 使用修改后的参数执行
        return pjp.proceed(trimmedArgs)
    }
}

第8章:拦截器链设计

拦截器链是 AOP 框架的核心,它管理多个拦截器的执行顺序,实现责任链模式。

8.1 拦截器接口设计

kotlin 复制代码
/**
 * 方法拦截器接口
 */
interface MethodInterceptor {

    /** 拦截器优先级(数值越小越先执行) */
    val order: Int

    /** 切入点匹配器 */
    val pointcut: PointcutMatcher

    /**
     * 拦截方法调用
     *
     * @param invocation 方法调用上下文
     * @return 方法返回值
     */
    fun invoke(invocation: MethodInvocation): Any?
}

/**
 * 方法调用上下文
 */
interface MethodInvocation {

    /** 连接点信息 */
    val joinPoint: ProceedingJoinPoint

    /**
     * 继续执行下一个拦截器或目标方法
     */
    fun proceed(): Any?
}

8.2 拦截器链执行流程

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                      拦截器链执行流程                           │
└─────────────────────────────────────────────────────────────────┘

调用 proxy.method()
        │
        ▼
┌───────────────────┐
│ InterceptorChain  │
│   开始执行        │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│ BeforeInterceptor │────▶│ 执行 @Before 通知 │
│    (order=1)      │     └───────────────────┘
└─────────┬─────────┘
          │ proceed()
          ▼
┌───────────────────┐     ┌───────────────────┐
│ AroundInterceptor │────▶│ 执行 @Around 前半 │
│    (order=2)      │     └───────────────────┘
└─────────┬─────────┘
          │ pjp.proceed()
          ▼
┌───────────────────┐     ┌───────────────────┐
│ 目标方法执行      │────▶│ 实际业务逻辑      │
└─────────┬─────────┘     └───────────────────┘
          │ 返回结果
          ▼
┌───────────────────┐     ┌───────────────────┐
│ AroundInterceptor │────▶│ 执行 @Around 后半 │
│    返回          │     └───────────────────┘
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│AfterReturning     │────▶│执行@AfterReturning│
│ Interceptor       │     └───────────────────┘
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│ AfterInterceptor  │────▶│ 执行 @After 通知  │
└─────────┬─────────┘     └───────────────────┘
          │
          ▼
      返回结果

拦截器链实现

kotlin 复制代码
/**
 * 拦截器链
 * 管理拦截器的执行顺序
 */
class InterceptorChain(
    private val interceptors: List<MethodInterceptor>,
    private val target: Any,
    private val method: Method,
    private val methodHandle: MethodHandle
) {

    /** 当前执行位置 */
    private var currentIndex = 0

    /**
     * 执行拦截器链
     */
    fun proceed(joinPoint: ProceedingJoinPoint): Any? {
        // 查找下一个匹配的拦截器
        while (currentIndex < interceptors.size) {
            val interceptor = interceptors[currentIndex]

            // 检查是否匹配当前方法
            if (interceptor.pointcut.matches(target::class.java, method)) {
                currentIndex++

                // 创建方法调用上下文
                val invocation = DefaultMethodInvocation(joinPoint, this)

                // 执行拦截器
                return interceptor.invoke(invocation)
            }

            currentIndex++
        }

        // 所有拦截器执行完毕,执行目标方法
        return (joinPoint as DefaultProceedingJoinPoint).invokeTarget()
    }

    /**
     * 创建新的拦截器链(用于 proceed 调用)
     */
    fun fork(): InterceptorChain {
        return InterceptorChain(interceptors, target, method, methodHandle).also {
            it.currentIndex = this.currentIndex
        }
    }
}

/**
 * 方法调用上下文默认实现
 */
class DefaultMethodInvocation(
    override val joinPoint: ProceedingJoinPoint,
    private val chain: InterceptorChain
) : MethodInvocation {

    override fun proceed(): Any? {
        return chain.proceed(joinPoint)
    }
}

8.3 五种通知类型的实现

Before 通知拦截器

kotlin 复制代码
/**
 * 前置通知拦截器
 * 在目标方法执行前执行
 */
class BeforeAdviceInterceptor(
    private val aspectInstance: Any,
    private val adviceMethod: Method,
    private val adviceMethodHandle: MethodHandle,
    override val pointcut: PointcutMatcher,
    override val order: Int
) : MethodInterceptor {

    override fun invoke(invocation: MethodInvocation): Any? {
        // 执行前置通知
        invokeAdvice(invocation.joinPoint)

        // 继续执行链
        return invocation.proceed()
    }

    private fun invokeAdvice(joinPoint: JoinPoint) {
        val params = adviceMethod.parameters

        when {
            params.isEmpty() -> {
                adviceMethodHandle.invoke(aspectInstance)
            }
            params.size == 1 && params[0].type.isAssignableFrom(JoinPoint::class.java) -> {
                adviceMethodHandle.invoke(aspectInstance, joinPoint)
            }
            else -> {
                throw IllegalArgumentException("@Before 方法参数不正确")
            }
        }
    }
}

After 通知拦截器

kotlin 复制代码
/**
 * 后置通知拦截器
 * 在目标方法执行后执行(无论是否异常)
 */
class AfterAdviceInterceptor(
    private val aspectInstance: Any,
    private val adviceMethod: Method,
    private val adviceMethodHandle: MethodHandle,
    override val pointcut: PointcutMatcher,
    override val order: Int
) : MethodInterceptor {

    override fun invoke(invocation: MethodInvocation): Any? {
        try {
            return invocation.proceed()
        } finally {
            // 无论是否异常,都执行后置通知
            invokeAdvice(invocation.joinPoint)
        }
    }

    private fun invokeAdvice(joinPoint: JoinPoint) {
        val params = adviceMethod.parameters

        when {
            params.isEmpty() -> {
                adviceMethodHandle.invoke(aspectInstance)
            }
            params.size == 1 && params[0].type.isAssignableFrom(JoinPoint::class.java) -> {
                adviceMethodHandle.invoke(aspectInstance, joinPoint)
            }
            else -> {
                throw IllegalArgumentException("@After 方法参数不正确")
            }
        }
    }
}

Around 通知拦截器

kotlin 复制代码
/**
 * 环绕通知拦截器
 * 包裹目标方法,可以完全控制执行流程
 */
class AroundAdviceInterceptor(
    private val aspectInstance: Any,
    private val adviceMethod: Method,
    private val adviceMethodHandle: MethodHandle,
    override val pointcut: PointcutMatcher,
    override val order: Int
) : MethodInterceptor {

    override fun invoke(invocation: MethodInvocation): Any? {
        val joinPoint = invocation.joinPoint as ProceedingJoinPoint

        // 创建一个包装的 ProceedingJoinPoint
        // 当调用 proceed() 时,继续执行拦截器链
        val wrappedJoinPoint = object : ProceedingJoinPoint by joinPoint {
            override fun proceed(): Any? {
                return invocation.proceed()
            }

            override fun proceed(args: Array<Any?>): Any? {
                // 更新参数后继续执行
                return invocation.proceed()
            }
        }

        // 执行环绕通知
        return adviceMethodHandle.invoke(aspectInstance, wrappedJoinPoint)
    }
}

AfterReturning 通知拦截器

kotlin 复制代码
/**
 * 返回通知拦截器
 * 在目标方法正常返回后执行
 */
class AfterReturningAdviceInterceptor(
    private val aspectInstance: Any,
    private val adviceMethod: Method,
    private val adviceMethodHandle: MethodHandle,
    override val pointcut: PointcutMatcher,
    override val order: Int,
    private val returningParamName: String
) : MethodInterceptor {

    override fun invoke(invocation: MethodInvocation): Any? {
        // 执行目标方法
        val result = invocation.proceed()

        // 执行返回通知
        invokeAdvice(invocation.joinPoint, result)

        return result
    }

    private fun invokeAdvice(joinPoint: JoinPoint, result: Any?) {
        val params = adviceMethod.parameters

        when (params.size) {
            0 -> {
                adviceMethodHandle.invoke(aspectInstance)
            }
            1 -> {
                if (params[0].type.isAssignableFrom(JoinPoint::class.java)) {
                    adviceMethodHandle.invoke(aspectInstance, joinPoint)
                } else {
                    // 参数是返回值
                    adviceMethodHandle.invoke(aspectInstance, result)
                }
            }
            2 -> {
                // 第一个参数是 JoinPoint,第二个是返回值
                adviceMethodHandle.invoke(aspectInstance, joinPoint, result)
            }
            else -> {
                throw IllegalArgumentException("@AfterReturning 方法参数不正确")
            }
        }
    }
}

AfterThrowing 通知拦截器

kotlin 复制代码
/**
 * 异常通知拦截器
 * 在目标方法抛出异常后执行
 */
class AfterThrowingAdviceInterceptor(
    private val aspectInstance: Any,
    private val adviceMethod: Method,
    private val adviceMethodHandle: MethodHandle,
    override val pointcut: PointcutMatcher,
    override val order: Int,
    private val throwingParamName: String
) : MethodInterceptor {

    override fun invoke(invocation: MethodInvocation): Any? {
        try {
            return invocation.proceed()
        } catch (e: Throwable) {
            // 执行异常通知
            invokeAdvice(invocation.joinPoint, e)

            // 重新抛出异常
            throw e
        }
    }

    private fun invokeAdvice(joinPoint: JoinPoint, exception: Throwable) {
        val params = adviceMethod.parameters

        when (params.size) {
            0 -> {
                adviceMethodHandle.invoke(aspectInstance)
            }
            1 -> {
                if (params[0].type.isAssignableFrom(JoinPoint::class.java)) {
                    adviceMethodHandle.invoke(aspectInstance, joinPoint)
                } else if (params[0].type.isAssignableFrom(Throwable::class.java)) {
                    adviceMethodHandle.invoke(aspectInstance, exception)
                }
            }
            2 -> {
                // 第一个参数是 JoinPoint,第二个是异常
                adviceMethodHandle.invoke(aspectInstance, joinPoint, exception)
            }
            else -> {
                throw IllegalArgumentException("@AfterThrowing 方法参数不正确")
            }
        }
    }
}

8.4 拦截器排序

多个拦截器需要按照正确的顺序执行:

kotlin 复制代码
/**
 * 拦截器排序器
 */
object InterceptorSorter {

    /**
     * 对拦截器进行排序
     *
     * 排序规则:
     * 1. 按 order 升序(数值小的先执行)
     * 2. 同 order 时,按类型排序:Before < Around < AfterReturning < AfterThrowing < After
     */
    fun sort(interceptors: List<MethodInterceptor>): List<MethodInterceptor> {
        return interceptors.sortedWith(
            compareBy<MethodInterceptor> { it.order }
                .thenBy { getTypeOrder(it) }
        )
    }

    private fun getTypeOrder(interceptor: MethodInterceptor): Int {
        return when (interceptor) {
            is BeforeAdviceInterceptor -> 0
            is AroundAdviceInterceptor -> 1
            is AfterReturningAdviceInterceptor -> 2
            is AfterThrowingAdviceInterceptor -> 3
            is AfterAdviceInterceptor -> 4
            else -> 5
        }
    }
}

8.5 本章小结

在本章中,我们设计了 AOP 框架的核心组件:

  1. JoinPoint:封装连接点信息,提供目标方法的上下文
  2. ProceedingJoinPoint:扩展 JoinPoint,支持执行目标方法
  3. MethodInterceptor:方法拦截器接口
  4. InterceptorChain:拦截器链,管理执行顺序
  5. 五种通知拦截器:Before、After、Around、AfterReturning、AfterThrowing

关键设计决策:

设计点 决策 原因
执行顺序 责任链模式 灵活、可扩展
方法调用 MethodHandle 高性能
参数传递 支持修改参数 灵活性
异常处理 保持原始异常 不影响业务逻辑
游客

全部评论 (0)

暂无评论,快来抢沙发吧~