AOP面向切面编程,解决代码复用问题,将与主业务逻辑无关的代码(如日志,事务,安全检查等)分离,实现解耦。
一、 应用场景:
1.日志记录
2.事务
3.权限
4.性能监控
5.异常处理
二、底层实现原理
动态代理
JDK
基于接口
CGLIB
基于字节码(继承)
可以参考代理模式章节https://blog.csdn.net/qq_32285039/article/details/104192459
三、 AOP术语
1.切面:切面泛指交叉业务逻辑。比如事务处理、日志处理就可以理解为切面。常用的切面有通知与顾问。实际就是对主业务逻辑的一种增强
2.织入:织入是指将切面代码插入到目标对象的过程。
3.连接点:连接点指切面可以织入的位置。
4.切点:切入点指切面具体织入的位置。
5.通知:通知是切面的一种实现,可以完成简单织入功能(织入功能就是在这里完成的)。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
6.顾问:顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。 不仅指定了切入时间点,还可以指定具体的切入点。
四、通知类型
1.前置通知@Before
目标方法执行之前调用
2.后置通知@AfterReturning
目标方法执行完成之后调用
3.环绕通知@Around
目标方法执行前后都会调用方法,且能增强结果
4.异常通知@AfterThrowing
目标方法出现异常调用
5.最终通知 @After
无论程序执行是否正常,该通知都会执行。类似于try..catch中finally代码块
五、具体实现
1.添加依赖
AspectJ的使用(以前置通知为例)
1.添加AspectJ的注解
2.创建相关业务类
3.创建切面类
4.测试结果
六、切入点表达式
execution | 定位到目标对象的方法上 |
within | 定位到具体的类型上 |
this | 代理对象的类型 |
target | 目标对象的类型 |
args | 参数的类型 |
@args | 传入的参数有被该注解修饰 |
@within | 类型修饰的注解 |
@annotation | 方法修饰的注解 |
七、execution表达式
* | 0到多个符合 |
.. | 方法参数中表示任意个参数,用在包名后表示当前包及其子包 |
+ | 用在类名后表示当前类及其子类,用在接口后表接口及其实现 |
实例:
execution(public * *(. .)) | 指定切入点为:任意公共方法 |
execution(* set *(. .)) | 指定切入点为:任何一个以“set”开始的方法 |
execution(* com.xyz.service.*.*(. .)) | 指定切入点为:定义在service包里的任意类的任意方法 |
execution(* com.xyz.service. .*.*(. .)) | 指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时,后面必须跟“*”,表示包、子包下的所有类。 |
execution(* *.service.*.*(. .)) | 指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点 |
execution(* *. .service.*.*(. .)) | 指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点 |