【Spring AOP】Spring AOP之如何通过注解的方式实现各种通知类型的AOP操作进阶篇(3)

一、切入点表达式的各种类型

切入点表达式的作用:限制连接点的匹配(满足时对应的aspect方法会被执行)

1)execution:用于匹配方法执行连接点。Spring AOP用户可能最经常使用execution切入点指示器

执行表达式的格式如下:

  execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

    modifiers-pattern 指定访问修饰符如public

    ret-type-pattern 指定返回类型如void;*是最常用的返回类型模式。它匹配任何返回类型
    declaring-type-pattern 指定类的全路径名称如com.zbq.springbootdemo.Myservice;如果指定了,通过 . 符号将其连接到name-pattern
    name-pattern 指定方法名称如get;您可以使用*通配符作为名称模式的全部或部分
    param-pattern 指定参数类型如String;()匹配不带参数的方法,而(..)匹配任意数量(零或更多)的参数。(*)模式匹配接受任意类型参数的方法;(*,String)匹配一个带有两个参数的方法。第一个可以是任何类型,第二个必须是字符串
    throws-pattern 指定抛出的异常类型
  除了返回类型模式(前面代码段中的rt-type-pattern)、name-pattern和param-pattern之外,其他所有部分都是可选的。

AspectJ类型匹配的通配符:·

         *:匹配任何数量字符;

         ..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

         +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

java.lang.String    匹配String类型;  
java.*.String       匹配java包下的任何“一级子包”下的String类型;  
            如匹配java.lang.String,但不匹配java.lang.ss.String  
java..*            匹配java包及任何子包下的任何类型;  
                   如匹配java.lang.String、java.lang.annotation.Annotation  
java.lang.*ing      匹配任何java.lang包下的以ing结尾的类型;  
java.lang.Number+  匹配java.lang包下的任何Number的自类型;  
                   如匹配java.lang.Integer,也匹配java.math.BigInteger 
 // 执行任何公用方法
    @Pointcut("execution(public * *(..))")
    private void pointcut1() {
    }

    // 任何以set开头的方法的执行:
    @Pointcut("  execution(* set*(..))")
    private void pointcut2() {
    }

    // 执行MyService接口定义的任何方法:
    @Pointcut("execution(* com.zbq.springbootdemo.service.MyService.*(..))")
    private void pointcut3() {
    }

    // 执行service包中定义的任何方法
    @Pointcut("execution(* com.zbq.springbootdemo.service..*(..))")
    private void pointcut4() {
    }

    // 执行service包及其子包中定义的任何方法
    @Pointcut("execution(* com.zbq.springbootdemo.service..*.*(..))")
    private void pointcut5() {
    }

2)within:用于匹配指定类型内的方法执行,限制对某些类型的匹配即满足指定的条件类,使用Spring AOP时匹配的类型中声明的方法被执行。和execution不一样的是,execution针对的是方法而within针对的是类

// 指定具体类中定义的任何方法
    @Pointcut("within(com.zbq.springbootdemo.service.MyService)")
    private void pointcut6_1() {
    }
    
    // 执行service包中定义的任何方法
    @Pointcut("within(com.zbq.springbootdemo.service.*)")
    private void pointcut6() {
    }

    // 执行service包及其子包中定义的任何方法
    @Pointcut("within(com.zbq.springbootdemo.service..*)")
    private void pointcut7() {
    }

3)this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配

// 代理实现MyService接口的任何连接点(仅在Spring AOP中执行方法):
    @Pointcut("this(com.zbq.springbootdemo.service.MyService)")
    private void pointcut8() {
    }

4)target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配

  // 目标对象实现MyService接口的任何连接点(仅在Spring AOP中执行方法)
    @Pointcut("target(com.zbq.springbootdemo.service.MyService)")
    private void pointcut9() {
    }

5)args:用于匹配当前执行的方法传入的参数为指定类型的执行方法·

 // 任何接受单个参数的连接点(只有在Spring AOP中才执行方法),并且在运行时传递的参数是可序列化的:
    // 注意和execution(* *(java.io.Serializable))区分开,args(java.io.Serializable)表示在运行时传递的参数是可序列化的,后者表示参数是Serializable类型的
    @Pointcut("args(java.io.Serializable)")
    private void pointcut10() {
    }

6)@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解

// 目标对象具有@MyAnnotation注释的任何连接点(仅在Spring AOP中执行方法):
    @Pointcut("@target(com.zbq.springbootdemo.common.annotation.MyAnnotation))")
    private void pointcut11() {
    }

7)@args:用于匹配当前执行的方法传入的参数持有指定注解的执行

// 任何接受单个参数的连接点(仅在Spring AOP中执行方法),其中传递的参数的运行时类型有@classification注解:
    @Pointcut("@args(com.xyz.security.Classified)")
    private void pointcut14() {
    }

8)@within:用于匹配所有持有指定注解类型内的方法,作用和@target类似

// 目标对象的声明类型具有@Transactional注释的任何连接点(仅在Spring AOP中执行方法):
    @Pointcut("@within(com.zbq.springbootdemo.common.annotation.MyAnnotation)")
    private void pointcut12() {
    }

9)@annotation:用于匹配当前执行方法持有指定注解的方法

// 任何连接点(仅在Spring AOP中执行方法),其中执行方法具有@MyAnnotation注解:
    @Pointcut("@annotation(com.zbq.springbootdemo.common.annotation.MyAnnotation)")
    private void pointcut13() {
    }

10)bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法

 // 在名为tradeService的Spring bean上的任何连接点(仅在Spring AOP中执行方法):
    @Pointcut("bean(tradeService)")
    private void pointcut15() {
    }

    // 在具有匹配通配符表达式*Service的名称的Spring bean上的任何连接点(仅在Spring AOP中执行方法):
    @Pointcut("bean(*Service)")
    private void pointcut16() {
    }

二、切入点表达式的使用

1)命名切入点可以被其他切入点引用,而匿名切入点是不可以的

   @Pointcut("execution(* com.zbq.springbootdemo.service.MyService.*(..))")
    public void myPointcut() {
    }
@Before(
"myPointcut()") public void before() { log.info("before "); }

2)可以使用&&、||和!组合切入点表达式。您还可以通过名称引用切入点表达式。下面的例子展示了三个切入点表达式

   /** 可以使用&&、||和!组合切入点表达式。您还可以通过名称引用切入点表达式。下面的例子展示了三个切入点表达式: */
    /**
     * 任何公共方法
     */
    @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() {
    }

    /**
     * springbootdemo包及其子包的所有方法
     */
    @Pointcut("within(com.zbq.springbootdemo..*)")
    private void inTrading() {
    }

    @Pointcut("anyPublicOperation() && inTrading()")
    private void tradingOperation() {
    }

3)将新的接口(和相应的实现)引入任何被建议的对象

 @DeclareParents(value="com.zbq.springbootdemo.service..*", defaultImpl=MyOperationManager.class)
    public static MyOperation myOperation;
    
    @After("execution(* com.zbq.springbootdemo.service.MyService.*(..)) && this(myOperation)" )
    public void after(JoinPoint joinPoint, MyOperation myOperation) {
        myOperation.operation();
        log.info("after ");
    }
// 原本的对象就可以强转为指定的接口
    MyOperation myOperation = (MyOperation) context.getBean("myService");

  

猜你喜欢

转载自www.cnblogs.com/756623607-zhang/p/11875910.html