# dummy-aop
**Repository Path**: phial3/dummy-aop
## Basic Information
- **Project Name**: dummy-aop
- **Description**: 简易的AOP(脱离Spring环境),适合初学者用于研究Spring AOP源码
- **Primary Language**: Unknown
- **License**: GPL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 8
- **Created**: 2024-03-15
- **Last Updated**: 2024-03-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 简易的AOP
- 不依赖IoC容器,可独立使用
- 支持AspectJ
## 学习方式
- 先把下面这篇《AOP的核心原理简介》看完,理解AOP最核心的概念。
- 然后pull dummy-aop到本地,把测试案例都跑一遍,沿着测试案例debug几遍,把流程搞清楚。
- 最后,可以尝试把dummy-ioc和dummy-aop两个项目整合起来,得到完整的dummy-spring(通过BeanPostProcessor)。
## AOP的核心原理简介
在一般大众的认知中,AOP就是在方法的前后做一些事情(Spring默认也就是方法级别的AOP)。
这是一个很普通的方法UserService#sayHello。
如何在sayHello前后做一些事情呢?最粗暴的做法是:
但这并不符合开闭原则,也不通用。如果需要在OrderService#order方法前后也做一些事情,就要把代码拷贝一份。
所以,我们必须将**sayHello**和**sayHello前后要做的事情**进行分离,而分离的目的是为了下次更好的相聚(组合)。
Spring AOP的做法是,抽象出以下概念:
- `Pointcut`
- `Advice`
- `Advisor`
`Pointcut`俗称切点,可以简单理解为“怎么切/切哪里”,通常是一个**匹配规则**。 比如AspectJ的`AspectJExpressionPointcut`,允许我们配置切点表达式:
> execution(* com.bravo.test.service.UserService.sayHello(..))
`Advice`则是具体的**增强逻辑**,即前面说的“方法前后要做的事情”。
而`Advisor` = `Pointcut` + `Advice`。 **对于符合Pointcut规则的目标方法应用Advice,以求在目标方法前后做一些事情。**
所以,上面拆开的sayHello和sayHello前后要做的事现在要产生联系了:
Spring把这个匹配过程封装在了AdvisorChainFactory中,代码大致如下:
Advisor持有Pointcut,方法匹配成功,则返回advice用于增强当前方法。
尽管在我看来这些`Advisor`、`Advice`、`Pointcut`这些概念已经很清晰,但对于初学者来说可能仍然有点绕。
所以,下面的讲解中,我再做一步简化,只留下Advice的概念,丢弃Pointcut和Advisor(dummy-aop会保留这些概念)。
没有Pointcut怎么知道哪些方法需要增强呢?交给调用者手动组装。比如:
讲到这,对于如何实现AOP应该有一个模糊的概念了。
接下来我们讨论最难的两个问题:
- 如何把advice嵌入目标方法前后
- 如何链式执行advice
所谓AOP,就是在调用目标方法前后额外执行一些逻辑。整个过程大致如下:
Method#invoke负责执行目标方法,额外的一些事情交给Advice去做。
在这里,Spring又抽象出了一个新的概念:`MethodInvocation`。它把上面整个流程进行了封装。
即把“Method执行前后需要额外做一些操作”这个过程抽象成MethodInvocation(method和method之前的操作打包在一块)。
Method是Java对**方法**的抽象,它包含一个方法的所有信息,如名称、参数和返回类型。
而MethodInvocation则是Spring对**方法调用**的抽象,更偏向**动态**的概念,调用proceed时会额外执行Advice。
MethodInvocation最重要的实现类是ReflectiveMethodInvocation,其主要成员变量包括:
- Method
- MethodInterceptorChain
想要使用MethodInvocation调用方法,则必然要先经过一串Interceptor。
> MethodInterceptor是AOP联盟的,Advice是Spring自己定义的。Spring底层把Advice适配成MethodInterceptor。
> MethodInterceptor比Advice更加见名知意,也和MethodInvocation更搭。
接着,我们使用JDK动态代理为userService生成代理对象。代理对象会将一次方法调用委托到目标对象,但在此之前会执行advice:
那么,如何产生链式调用呢?
MethodInvocation就是Filter模式中的FilterChain,持有Interceptor并且负责推进下一个Interceptor。
上面这个案例是极简的AOP,我放在 [设计模式那些事儿](https://gitee.com/bravo1988/design-pattern) 中,搞懂以后再研究dummy-aop。
搞懂以后再看dummy-aop的代码。
## 推荐
- [dummy-ioc](https://gitee.com/bravo1988/dummy-ioc)
- [设计模式那些事儿](https://gitee.com/bravo1988/design-pattern)