Aop
概述:Aspect Oriented Programming(面向切面编程、面向方面编程),即面向特定的方法编程,对原有的方法进行附加、增强
动态代理是面向切面编程的主流实现
实现步骤
- pom文件中导入AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-start-aop</artifactId>
</dependency>
2.创建一个面向Aop编程的一个类
案例部分功能运行较慢,定位耗时比较长的业务方法,此时需要统计每一个业务方法的执行耗时
优点:
1.代码无入侵
2.减少重复代码
3.提高开发效率
4.维护方便
核心概念
1.连接点:JoinPoint,可以被Aop控制的方法
2.通知:Advice,指哪些重复的逻辑,也就是共性功能
3.切入点:PointCut,匹配连接点的条件
4.切面:Aspect,通知+切入点
5.目标对象,Target,通知所应用的对象
Aop进阶
1.通知类型
@Around:环绕通知,此标注的通知方法在目标方法前后都被执行
1.环绕通知需要自己调用ProceedingJoinPoint.proceed()。
2.环绕通知的返回类型为Object
@Before:前置通知,在目标方法前执行
@After:后置通知,在目标方法后执行,无论是否异常都执行
@AfterReturning:返回后通知,在目标方法后执行,有异常不会执行
@AfterThrowing:异常后通知,发生异常后执行
切入点表达式的抽取
//抽取切入点,@pointcut
@Pointcut("execution(* com.learn.service.serviceImpl.*.(**))")
public void pt(){};
//引用
@Before("pt()")
private void before(){}
//privite表示只有当前类可以抽取,public表示所有类都可以抽取
2.多个切面类通知执行的顺序
1.可以在切面类添加@Order(数字)注解来控制顺序
2.对于目标方法执行前的通知,数字小的先执行
3.对于目标方法执行后的通知,数字小的后执行
3.切入点表达式
1.execution(…):根据方法的签名来匹配
execution(访问修饰符 返回值 包名.类名.方法名(方法参数) throws 异常 )
访问修饰符,包名、类名,异常都可以省略,但是包名和类名省略的话,可能出错
在使用的过程中,可以使用通配符来描述切入点
1." * ",单个独立的任意符号,返回值、包名、类名、方法名、任意类型的一个参数
2. " … "多个连续的任意符号,可以通配任意层级的包、类型、任意个数的参数。
如果是比较复杂的切入点表达式,或者想要调用多个方法,切入点的表达式可以用 || 、 &&、 !
注意事项
- 业务层的命名方法需要统一规范,如查询方法名都以find开头
- 描述切点的方法通常基于接口描述,而不是直接描述实现类
- 满足业务需求的前提下,尽量缩小切入点的范围
2.@annotation(…):根据注解匹配
用于匹配标识有特定注解的方法
1.自定义切面注解,右键新建一个Annotation文件
2.添加注解@Retention,指定什么时候生效
3.添加@Target注解,指定生效的地方
4.在业务层对应的方法添加@注解的类名,如@MyLog
5.在切面类的切入点添加自定义的注解路径
4.连接点
1.对于@Around的通知,获取连接点信息,只能使用ProceedingJoinPoint
2.对于其他四种通知,获取连接点的信息只能用JoinPoint,他是ProceedingJoinPoint的父类