探秘Spring AOP
- designators 指示器包括如下:
一、匹配包、类型 within
/** * 匹配WithinService类里头的所有方法 * @Pointcut("within(cn.evchar.aop.within.WithinService)") * 匹配com.imooc包及子包下所有类的方法 * @Pointcut("within(cn.evchar.aop.within..*)") */@Aspect@Componentpublic 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@Componentpublic 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@Componentpublic 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 ,,,
/** * //匹配方法标注有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@Componentpublic 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@Componentpublic 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"); }}