Spring AOP总结
Spring官方整合了AspectJ框架作为aop的实现之一,同时自己提供了Scheme Base的方式,由于AspectJ支持注解式的开发,现在大多使用AspectJ
JoinPoint 对象
JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象
常用API:
方法名 | 功能 |
---|---|
Signature getSignature(); | 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 |
Object[] getArgs(); | 获取传入目标方法的参数对象 |
Object getTarget(); | 获取被代理的对象 |
Object getThis(); | 获取代理对象 |
ProceedingJoinPoint对象
ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中
添加了
Object proceed() throws Throwable //执行目标方法
Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法
两个方法
@Pointcut的用法
@Pointcut用来指定切入点,一般使用切入点表达式
切入点表达式不止有execution这一种:
execution:表示匹配到的方法将被拦截
within:表示指定类型的所有方法将被拦截
- “within(com.elim.spring.aop.service.UserServiceImpl)”匹配UserServiceImpl类对应对象的所有方法外部调用,而且这个对象只能是UserServiceImpl类型,不能是其子类型。
- “within(com.elim…*)”匹配com.elim包及其子包下面所有的类的所有方法的外部调用。
this:this表示代理对象.语法:this(Type),当生成的代理对象可以转化为type指定的类型则表示匹配(注意动态代理的实现方式不一样代理对象不一样)
- “this(com.elim.spring.aop.service.IUserService)”匹配生成的代理对象是IUserService类型的所有方法的外部调用。
target:target表示被代理对象,语法同上,当被代理的对象为指定类型则表示匹配
- “target(com.elim.spring.aop.service.IUserService)”则匹配所有被代理的目标对象能够转换为IUserService类型的所有方法的外部调用。
args:用来匹配方法参数
- “args()”匹配任何不带参数的方法
- “args(java.lang.String)”匹配任何只带一个参数,而且这个参数的类型是String的方法。
- “args(…)”带任意参数的方法。
- “args(java.lang.String,…)”匹配带任意个参数,但是第一个参数的类型是String的方法。
- “args(…,java.lang.String)”匹配带任意个参数,但是最后一个参数的类型是String的方法。
@target:@target匹配当被代理的目标对象对应的类型及其父类型上拥有指定的注解时
- “@target(com.elim.spring.support.MyAnnotation)”匹配被代理的目标对象对应的类型上拥有MyAnnotation注解时。
@args:@args匹配被调用的方法上含有参数,且对应的参数类型上拥有指定的注解的情况
- “@args(com.elim.spring.support.MyAnnotation)”匹配方法参数类型上拥有MyAnnotation注解的方法调用。如我们有一个方法add(MyParam param)接收一个MyParam类型的参数,而MyParam这个类是拥有注解MyAnnotation的,则它可以被Pointcut表达式“@args(com.elim.spring.support.MyAnnotation)”匹配上。
@within:@within用于匹配被代理的目标对象对应的类型或其父类型拥有指定的注解的情况,但只有在调用拥有指定注解的类上的方法时才匹配
- “@within(com.elim.spring.support.MyAnnotation)”匹配被调用的方法声明的类上拥有MyAnnotation注解的情况。比如有一个ClassA上使用了注解MyAnnotation标注,并且定义了一个方法a(),那么在调用ClassA.a()方法时将匹配该Pointcut;如果有一个ClassB上没有MyAnnotation注解,但是它继承自ClassA,同时它上面定义了一个方法b(),那么在调用ClassB().b()方法时不会匹配该Pointcut,但是在调用ClassB().a()时将匹配该方法调用,因为a()是定义在父类型ClassA上的,且ClassA上使用了MyAnnotation注解。但是如果子类ClassB覆写了父类ClassA的a()方法,则调用ClassB.a()方法时也不匹配该Pointcut
@annotation:@annotation用于匹配方法上拥有指定注解的情况
- “@annotation(com.elim.spring.support.MyAnnotation)”匹配所有的方法上拥有MyAnnotation注解的方法外部调用。
bean:bean用于匹配当调用的是指定的Spring的某个bean的方法时。
- “bean(abc)”匹配Spring Bean容器中id或name为abc的bean的方法调用。
- “bean(user*)”匹配所有id或name为以user开头的bean的方法调用。
/**
* 切入点表达式语法:
* execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
*
* 修饰符匹配(modifier-pattern?)
* 返回值匹配(ret-type-pattern)可以为*表示任何返回值,全路径的类名等
* 类路径匹配(declaring-type-pattern?)
* 方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, set* 代表以set开头的所有方法
* 参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可 以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数
* 异常类型匹配(throws-pattern?)其中后面跟着“?”的是可选项
*
*/
@Pointcut("execution(* com.*.*(..))")
private void aopPointcut() {}
/**
* Pointcut定义时,还可以使用&&、||、! 这三个运算
*
*/
@Pointcut("aopPointcut() || execution(* com.*..*(..))")
private void aopPointcut2() {}