文章目录
面向切面编程
一、什么是面向切面AOP
1、为什么需要面向切面
-
前面提到了代理模式,可以极大的减少代码编写量,减少了代码耦合度,并且提高了可维护性
-
交叉业务:假设每个方法都需要日志/事务/权限,这些重复通用的业务和业务代码混杂在一起。交叉业务过多,就会导致以下两个问题
- 第一:交叉业务代码在多个业务流程中反复出现,显然这个交叉业务代码没有得到复用。并且修改这些交又业务代码的话,需要修改多处。(维护不便)
- 第二:程序员无法专注核心业务代码的编写,在编写核心业务代码的同时还需要处理这些交叉业务。
-
结合老杜的横向编程的图,更好理解
2、面向切面编程的优点
- 将于业务逻辑无关的通用业务逻辑代码单独提取出来,减少了对业务代码的干扰
- 便于维护
- 减少了代码编写量(冗余
- 遵循了OCP开闭原则,并且实现了解耦,降低了代码的耦合度
3、Spring的动态代理AOP
Sporng的AOP使用的代理是:JDK理 + GL1B动理技术Spring在这两种动态代理中灵活切换的
- 如果是代理接口,会从使用JDK动态代理
- 如果没有实现接口(普通类),就会切换使用CGLIB。
当然,你也可以强制通过一些配置让Spring只使用CGLIB。
学到这里,在脑子里就要有个概念:
当涉及到 交叉业务 以及各种类似的场景时,就要考虑是否要引入AOP了
二、AOP的七大术语!
连接点、切点、通知、切面、织入、代理对象、目标对象
PS:经过核实,老杜在将连接点和切点其实将反了,具体可以参考一些其他老师的内容连接点(Jointpoint)、切入点(Pointcut)、Spring AOP术语:连接点和切点的区别。讲得比较详细。
大体上可以认为:
连接点其实才是方法,而切点则可以认为是连接点的集合
1、连接点(JoinPoint)
- 表示需要在程序中插入横切关注点的扩展点
- 连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等
- Spring只支持方法执行作为连接点
- 在AOP中表示为“在哪里干”;
2、切点(PointCut)
- 选择一组相关连接点的模式,即可以认为连接点的集合
- 一个切点 对应多个连接点
- Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法
- 在AOP中表示为“在哪里干的集合”;
3、通知 or 增强(Advice)
- 通知,又称为增强,就是具体我们要织入的代码(逻辑)
- 通知描述的就是代码
- 通知分类(根据连接点的不同进行分类
- 前置通知:执行方法前,
- 后置通知:执行方法后
- 环绕通知:执行方法前后都有
- 异常通知:在捕获异常时通知
- 最终通知:在异常捕获的finally语句块中
4、切面(Aspect)
切点+通知 就是切面
可以这么理解,切点其实的多个点形成的线,加上具体的增强就形成了横向的切面
5、织入 Weaving
把通知应用到目标对象上的过程
6、代理对象 Proxy
目标对象被织入通知后,产生的新对象
7、目标对象 target
被织入通知的对象
三、切点表达式
1、切点表达式
切点表达式就是用来定义 通知 (Advice) 往哪些方法上 切入的。
- 用于定义通知切入
- 而且不局限于某个方法,可以切入多个方法
- 告诉程序,这个切点可以匹配哪些方法
2、切点表达式的格式
execution([访问控制权限修饰符] 返回值类型 [全限定类名]方法名(形参)) [异常])
-
访问权限修饰符:可选
- 默认是4个权限都包括
- 只写public就表示只包括公开的方法。
-
返回值类型:必填
- 星号
*
表示返回值类型为任意
- 星号
-
全限定名:可选
- 也就是类名,而且是具体的地址
- 两个点
..
代表当前包及其子包下所有的类 - 省略时,表示所有的类
-
方法名:必填
- 星号
*
表示所有方法 - 比如
set*
表示所有的set方法
- 星号
-
形式参数列表: 必填
()
——表示没有参数的方法(..)
——参数类型和个数随意的方法(*)
—— 只有一个参数的方法(*,String)
—— 第一个参数随意,第二个参数是String的
-
异常:可选
- 省略时表示任意类型的异常