zoukankan      html  css  js  c++  java
  • 【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() {
        }
    // 指定注解并获取注解值,指定名称就行
        @Pointcut(value = "execution(* com.zbq.springbootdemo.service.MyService..*(..)) && @annotation(myAnnotation)")
        public void myPointcut4(MyAnnotation myAnnotation) {
        }

    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");

      

  • 相关阅读:
    【大数据】HDFS高可用
    【Redis】常用命令、问题排查、内存优化
    【OOM】记一次线上OOM解决全流程
    【Git】Github如何弥补提交记录contributions
    Hash算法与Hash碰撞
    【计算机基础】存储单位换算
    【大数据】技术选型对比
    【MQ】Kafka架构与原理
    【Git】Git常用命令合集
    【maven】基本知识点
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/11875910.html
Copyright © 2011-2022 走看看