SpringAOP——JoinPoint和ProceedingJoinPoint AOP 的⼏个概念
名称解释
Pointcut 切点,决定处理如权限校验、⽇志记录等在何处切⼊业务代码中(即织⼊切⾯)。切点分为execution⽅式和annotation⽅式。前者可以⽤路径表达式指定哪些类织⼊切⾯,后者可以指定被哪些注解修饰的代码织⼊切⾯。
Advice 增强,包括处理时机和处理内容。处理内容就是要做什么事,⽐如校验权限和记录⽇志。处理时机就是在什么时机执⾏处理内容,分为前置处理
蒙以养正
(即业务代码执⾏前)、后置处理(业务代码执⾏后)等。
Aspect切⾯,即,Pointcut 和 Advice。
Joint
point
接⼊点,是程序执⾏的⼀个点。例如,⼀个⽅法的执⾏或者⼀个异常的处理。在 Spring AOP 中,⼀个
连接点总是代表⼀个⽅法执⾏Weaving织⼊,就是通过动态代理,在⽬标对象⽅法中执⾏处理内容的过程。
增强类型
1. 前置通知(Before Advice)
在某连接点(JoinPoint)之前执⾏的通知,但这个通知不能阻⽌连接点前的执⾏。ApplicationContext中在<aop:aspect>⾥⾯使⽤<aop:before>元素进⾏声明。
2. 后置通知(After Advice)
当某连接点退出的时候执⾏的通知(不论是正常返回还是异常退出)。ApplicationContext 中在<aop:aspect>⾥⾯使⽤<aop:after>元素进⾏声明。
3. 返回后通知(After Return Advice)
在某连接点正常完成后执⾏的通知,不包括抛出异常的情况。ApplicationContext 中在<aop:aspect>⾥⾯使⽤<after-returning>元素进⾏声明。
4. 异常通知(After Throwing Advice)
在 ⽅ 法 抛 出 异 常 退 出 时 执 ⾏ 的 通 知 。 ApplicationContext 中 在 <aop:aspect> ⾥ ⾯ 使 ⽤<aop:after-throwing>元素进⾏声明。
5. 环绕通知(Around Advice)
包围⼀个连接点的通知,类似 Web 中 Servlet 规范中的 Filter 的 doFilter ⽅法。可以在⽅法的调⽤前后完成⾃定义的⾏为,也可以选择不执⾏。ApplicationContext 中在<aop:aspect>⾥⾯使⽤<aop:around>元素进⾏声明。例如,ServiceAspect 中的 around ⽅法。
JoinPoint 和 ProceedingJoinPoint 的关系
AspectJ 使⽤ org.aspectj.lang.JoinPoint接⼝表⽰⽬标类连接点对象,如果是环绕增强时,使⽤org.as
pectj.lang.ProceedingJoinPoint表⽰连接点对象,该类是JoinPoint的⼦接⼝。任何⼀个增强⽅法都可以通过将第⼀个⼊参声明为JoinPoint访问到连接点上下⽂的信息。
在增强(advice)⽅法中可以声明⼀个JoinPoint类型的参数, 通过JoinPoint可以访问连接点的细节。
JoinPoint
JoinPoint对象封装了SpringAop中切⾯⽅法的信息, 在切⾯⽅法中添加JoinPoint参数,就可以获取到封装了该⽅法信息:
1. 切⼊点的⽅法名字及其参数;
2. 切⼊点⽅法标注的注解对象(通过该对象可以获取注解信息);
3. 切⼊点⽬标对象(可以通过反射获取对象的类名,属性和⽅法名)。
例如:
亲子厨房/**
* 切点:
水晶肉* 定义⼀个切⼊点表达式,⽤来确定哪些类需要代理
* 代表com.rvice包下UrService类的create*⽅法都会被代理
*/
@Pointcut("execution(* com.ate*(..))")
public void create(){}
/**
进bios* 前置增强:在⽬标⽅法执⾏前执⾏
*/
@Before(value ="create()")
public void before(JoinPoint joinPoint){
System.out.println("【"+Signature().getName()+"】⽅法执⾏,参数是:"+ Arrays.Args()));
System.out.Signature());
System.out.println("⽬标⽅法名为:"+ Signature().getName());
System.out.println("⽬标⽅法所属类的简单类名:"+ Signature().getDeclaringType().getSimpleName());
System.out.println("⽬标⽅法所属类的类名:"+ Signature().getDeclaringTypeName());
System.out.println("⽬标⽅法声明类型:"+ Signature().getModifiers()));
System.out.Args()));
System.out.Kind());
System.out.SourceLocation());
System.out.StaticPart());
System.out.Target());
System.out.This());家的写法
}
输出如下:
【createUr】⽅法执⾏,参数是:[⼋戒, 100]
Ur com.ateUr(String,int)
⽬标⽅法名为:createUr
⽬标⽅法所属类的简单类名:UrService
⽬标⽅法所属类的类名:com.rvice.UrService
⽬标⽅法声明类型:public abstract
[⼋戒, 100]
method-execution
org.springframework.aop.aspectj.
MethodInvocationProceedingJoinPoint$SourceLocationImpl@2101b44a
杨贵妃画像execution(Ur com.ateUr(String,int))
com.rvice.impl.UrServiceImpl@2cc3ad05
com.rvice.impl.UrServiceImpl@2cc3ad05
怎样做糖醋鱼常⽤ api
⽅法名功能
Signature getSignature();获取封装了署名信息的对象,在该对象中可以获取到⽬标⽅法名,所属类的Class等信息Object[] getArgs();获取传⼊⽬标⽅法的参数对象
Object getTarget();获取被代理的对象
Object getThis();获取代理对象
ProceedingJoinPoint
儿童青少年ProceedingJoinPoint继承JoinPoint⼦接⼝,它新增了两个⽤于执⾏连接点⽅法的⽅法
⽅法名功能
Object proceed() throws Throwable通过反射执⾏⽬标对象的连接点处的⽅法Object proceed(java.lang.Object[] args) throws Throwable通过反射执⾏⽬标对象连接点处的⽅法,不过使⽤新的参数替换原来的参数