第三部分:设计篇 - 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.ccom.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 设计
ProceedingJoinPoint 是 JoinPoint 的扩展,专门用于 @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 框架的核心组件:
- JoinPoint:封装连接点信息,提供目标方法的上下文
- ProceedingJoinPoint:扩展 JoinPoint,支持执行目标方法
- MethodInterceptor:方法拦截器接口
- InterceptorChain:拦截器链,管理执行顺序
- 五种通知拦截器:Before、After、Around、AfterReturning、AfterThrowing
关键设计决策:
| 设计点 | 决策 | 原因 |
|---|---|---|
| 执行顺序 | 责任链模式 | 灵活、可扩展 |
| 方法调用 | MethodHandle | 高性能 |
| 参数传递 | 支持修改参数 | 灵活性 |
| 异常处理 | 保持原始异常 | 不影响业务逻辑 |
全部评论 (0)
暂无评论,快来抢沙发吧~