SpringAOP
SpringAOP
AOP: Aspect Oriented Programming(面向切面编程、面向方面编程),可简单理解为面向特定方法编程。可以实现记录操作日志、事务管理、权限控制等操作。
步骤:
引入AOP依赖
编写AOP的程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DemoAspect {
public void before(){
...
}
public Object around(ProceedingJointPoint pjp) {
...
Object result = pjp.proceed();
...
return result;
}
}
核心概念:
- 连接点:JoinPoint,可以被AOP控制的方法
- 通知:Advice,指重复的逻辑,也就是共性功能,最终体现为一个方法
- 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
目标对象:Target,通知所应用的对象
实现原理:AOP使用了动态代理技术

通知类型
根据通知方法执行时机不同,分为:
@Around
:环绕通知,通知方法在目标方法运行前、后都被执行@Before
:前置通知,通知方法在目标方法运行前被执行@After
:后置通知,通知方法在目标方法运行后被执行,无论是否有异常都会执行@AfterReturning
:返回后通知,通知方法在目标方法运行后被执行,有异常不会执行@AfterThrowing
:异常后通知,通知方法在目标方法报异常后被执行
@Around
需要自己调用ProceedingJoinPoint.proceed()
来让原始方法执行,其他通知不需要。
@Around
的返回值必须指定为Object
以接收原始方法的返回值。
@Pointcut
注解可以将公共的切点表达式抽取出来:
1 | // 声明切入点 |
当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。
执行顺序:不同切面类中,默认按照切面类的类名字母排序:
- 目标方法前的通知方法:字母排名靠前的先执行
- 目标方法后的通知方法:字母排名靠前的后执行
可以通过在切面类上加上注解@Order(num)
控制执行顺序:
- 目标方法前的通知方法:数字小的先执行
- 目标方法后的通知方法:数字小的后执行
切入点表达式
描述切入点方法通常基于接口描述,增强拓展性。
常见形式:
execution(...)
:根据方法的签名来匹配,支持逻辑与或1
2
3execution(访问修饰符 返回值 包名.类名.方法名(方法参数) throws 异常)
execution(void top.eternity0126.service.impl.DeptServiceImpl.delete(java.lang.Integer))其中可省略的部分:
- 访问修饰符,如public、protected
- 包名.类名(不建议)
- throws 异常(对应声明上抛出的异常)
特殊符号:
*
:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分..
:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
annotation(...)
:根据注解匹配1
2
3
4
5
6
7
8
9
10
11
12
13// 定义
// 注解用于方法
// 注解运行时生效
public LogOperation {}
public void before(){
...
}
// 使用
...
连接点
Spring中用JoinPoint
抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
对于@Around
注解,只能使用ProceedingJoinPoint
,对于其他注解只能使用JoinPoint
(ProceedingJoinPoint
的父类)。
获取目标对象:
1
Object target = joinPoint.getTarget();
获取目标类:
1
String className = joinPoint.getTarget().getClass().getName();
获取目标方法:
1
String methodName = joinPoint.getSignature().getName();
获取目标方法参数:
1
Object[] args = joinPoint.getArgs();
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Eternity's Blog!