探秘Spring AOP
- designators 指示器包括如下:
一、匹配包、类型 within
/**
* 匹配WithinService类里头的所有方法
* @Pointcut("within(cn.evchar.aop.within.WithinService)")
* 匹配com.imooc包及子包下所有类的方法
* @Pointcut("within(cn.evchar.aop.within..*)")
*/
@Aspect
@Component
public class WithinAspectConfig {
@Pointcut("within(cn.evchar.aop.within..*)")
public void matchType(){ }
@Before("matchType()")
public void before(){
// 编写需要 织入
System.out.println("");
System.out.println("### before 开始织入逻辑");
}
}
二、匹配对象 bean, this, target
/**
*
* //匹配AOP对象的目标对象为指定类型的方法,即LogService的aop代理对象的方法
* @Pointcut("this(cn.evchar.aop.target.Loggable)")
*
* //匹配实现Loggable接口的目标对象(而不是aop代理后的对象)的方法
* @Pointcut("target(cn.evchar.aop.target.Loggable)")
*
* //this 可以拦截 DeclareParents(Introduction)
* //target 不拦截 DeclareParents(Introduction)
*
* //匹配所有以Service结尾的bean里头的方法
*
*/
@Aspect
@Component
public class ObjectAspectConfig {
@Pointcut("bean(logService)")
public void matchCondition(){}
// @Pointcut("this(cn.evchar.aop.target.Loggable)")
// public void matchCondition(){}
// @Pointcut("target(cn.evchar.aop.target.Loggable)")
// public void matchCondition(){}
@Before("matchCondition()")
public void before(){
System.out.println("");
System.out.println("### before ");
}
}
三、匹配参数 Args
/**
*
* //匹配任何以find开头而且只有一个Long参数的方法
* @Pointcut("execution(* *..find*(Long))")
* //匹配任何以find开头的而且第一个参数为Long型的方法
* @Pointcut("execution(* *..find*(Long,..))")
* //匹配任何只有一个Long参数的方法
* @Pointcut("within(cn.evchar.aop.service.*) && args(Long)")
* //匹配第一个参数为Long型的方法
* @Pointcut("within(cn.evchar.aop.service.*) && args(Long,..)")
*
*/
@Aspect
@Component
public class ArgAspectConfig {
// 匹配一个参数
@Pointcut("args(Long) && within(cn.evchar.aop.service.*)")
public void matchArgs(){}
// 匹配,两个参数,第二个为任意参数
// @Pointcut("args(Long,..) && within(cn.evchar.aop.service.*)")
// public void matchArgs(){}
// 匹配,两个具体类型参数
// @Pointcut("args(Long,String) && within(cn.evchar.aop.service.*)")
// public void matchArgs(){}
@Before("matchArgs()")
public void beforeArgs(){
System.out.println("");
System.out.println("#### before");
}
}
四、匹配注解 anno @annotation,@within,@target,@args
/**
* //匹配方法标注有AdminOnly的注解的方法
* @Pointcut("@annotation(cn.evchar.aop.anno.AdminOnly) && within(cn.evchar.aop..*)")
* //匹配标注有NeedSecured的类底下的方法 //class级别
* @Pointcut("@within(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
* //匹配标注有NeedSecured的类及其子类的方法 //runtime级别
* 在spring context的环境下,二者没有区别
* @Pointcut("@target(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
* //匹配传入的参数类标注有Repository注解的方法
* @Pointcut("@args(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
*
*/
@Aspect
@Component
public class AnnoAspectConfig {
// 方法上面注解
// @Pointcut("@annotation(cn.evchar.aop.anno.AdminOnly)")
// public void matchAnno(){}
// 类上面注解
// @Pointcut("@within(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
// public void matchAnno(){}
// 类上面注解
@Pointcut("@target(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
public void matchAnno(){}
// 参数上面注解
// @Pointcut("@args(cn.evchar.aop.anno.NeedSecured) && within(cn.evchar.aop..*)")
// public void matchAnno(){}
@Before("matchAnno()")
public void before(){
System.out.println("");
System.out.println("### before annotation ");
}
}
五、匹配方法 execution
标注 ? 部分,可以省略 ,其余必须存在。
execution(
modifier-pattern? 修饰符部分 例如 public private...
ret-type-pattern 返回值部分 例如 return String;
declaring-type-pattern? 描述包名 例如 cn.evchar....
name-pattern(param-pattern) 描述方法名,描述方法参数
throws-pattern? 匹配抛出的异常
)
/**
*
* 匹配任何公共方法
* @Pointcut("execution(public * cn.evchar.aop.service.*.*(..))")
*
* 匹配com.imooc包及子包下Service类中无参方法
* @Pointcut("execution(* cn.evchar.aop..*Service.*())")
*
* 匹配com.imooc包及子包下Service类中的任何只有一个参数的方法
* @Pointcut("execution(* cn.evchar.aop..*Service.*(*))")
*
* 匹配com.imooc包及子包下任何类的任何方法
* @Pointcut("execution(* cn.evchar.aop..*.*(..))")
*
* 匹配com.imooc包及子包下返回值为String的任何方法
* @Pointcut("execution(String cn.evchar.aop..*.*(..))")
*
* 匹配异常
* execution(public * cn.evchar.aop.service.*.*(..) throws java.lang.IllegalAccessException)
*
*/
@Aspect
@Component
public class ExecutionAspectConfig {
// 扫描包下面的类,不包括子包
// @Pointcut("execution(public * cn.evchar.aop.service.*Service.*(..))")
// public void matchExecution(){}
// 扫描包下面的所有类,包括子包
// @Pointcut("execution(public * cn.evchar.aop.service..*Service.*(..))")
// public void matchExecution(){}
// 拦截返回是String 类型
// @Pointcut("execution(public String cn.evchar.aop.service..*Service.*(..))")
// public void matchExecution(){}
// 拦截返回是void
// @Pointcut("execution(public String cn.evchar.aop.service..*Service.*(..))")
// public void matchExecution(){}
// 返回无参
// @Pointcut("execution(public String cn.evchar.aop.service..*Service.*())")
// public void matchExecution(){}
// 返回第一个参数Long 类型的
// @Pointcut("execution(public String cn.evchar.aop.service..*Service.*(Long))")
// public void matchExecution(){}
@Pointcut("execution(public String cn.evchar.aop.service..*Service.*(..) " +
"throws java.lang.IllegalAccessException)")
public void matchExecution(){}
@Before("matchExecution()")
public void before(){
System.out.println("");
System.out.println("#### before");
}
}