Spring AOP : AspectJ Pointcut 切点

Point cut

在 Spring 中, 所有的方法都可以认为是 joinpoint, 但是我们并不希望在所有的方法上都添加 Advice, 而 pointcut 的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配joinpoint, 给满足规则的 joinpoint 添加 Advice.

声明 pointcut

一个 pointcut 的声明由两部分组成:

  1. 一个方法签名, 包括方法名和相关参数
  2. 一个 pointcut 表达式, 用来指定哪些方法执行是我们感兴趣的(即因此可以织入 advice).

在@AspectJ 风格的 AOP 中, 我们使用一个方法来描述 pointcut, 即:
@Pointcut(“execution(* com.ailianshuo.springaop.sample03..*.*(..))”)

第一个表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示service包及其子包,第二个表示所有类,第三个*表示所有方法,第二个..表示方法的任意参数个数

/**
     * 定义一个切点然后复用
     * 这个方法必须无返回值.
     *这个方法本身就是 pointcut signature, pointcut 表达式使用@Pointcut 注解指定.
     *上面我们简单地定义了一个 pointcut, 这个 pointcut 所描述的是: 匹配所有在包   *com.ailianshuo.springaop.sample03.Math 下的所有方法的执行.
     */
    @Pointcut("execution(* com.ailianshuo.springaop.sample03.Math.*(..))")   // 切点表达式
    public void pointcutMath(){// 切点前面
    } 

    @Before("pointcutMath()")
    public void before(JoinPoint jp){
        //System.out.println(jp.getSignature().getName());
        System.out.println("----------before advice----------");
    } 
    @After("pointcutMath()")
    public void after_execution(JoinPoint jp){
        System.out.println("----------after execution advice----------");
    }

切点函数

切点函数可以定位到准确的横切逻辑位置
AspectJ 的切点表达式由标志符(designator)和操作参数组成. 如 “execution( greetTo(..))” 的切点表达式, execution 就是 标志符, 而圆括号里的 greetTo(..) 就是操作参数

@AspectJ使用AspectJ专门的切点表达式描述切面,Spring所支持的AspectJ表达式可分为四类:
方法切点函数:通过描述目标类方法信息定义连接点。
方法参数切点函数:通过描述目标类方法入参信息定义连接点。
目标类切点函数:通过描述目标类类型信息定义连接点。
代理类切点函数:通过描述代理类信息定义连接点。

常见的AspectJ表达式函数:
execution():满足匹配模式字符串的所有目标类方法的连接点
@annotation():任何标注了指定注解的目标方法链接点
args():目标类方法运行时参数的类型指定连接点
@args():目标类方法参数中是否有指定特定注解的连接点
within():匹配指定的包的所有连接点
target():匹配指定目标类的所有方法
@within():匹配目标对象拥有指定注解的类的所有方法
@target():匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
this():匹配当前AOP代理对象类型的所有执行方法
最常用的是:execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)切点函数,可以满足多数需求。

优先执行顺序:
annotation –> args –> execution –> this –> within

下面使用Spring实现AOP方式之二:使用注解配置 Spring AOP 中的样例继续开发讲解

样例

创建要被代理的StrUtil类

package com.ailianshuo.springaop.sample03;

import org.springframework.stereotype.Component;

@Component("strUtil")
public class StrUtil {
    public void show(){
        System.out.println("Hello StrUtil!");
    }
}

测试代码

package com.ailianshuo.springaop.sample03;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * AspectJ切点函数
 * 切点函数可以定位到准确的横切逻辑位置
 * @author ailianshuo
 * 2017年7月25日 下午11:42:57
 */
public class Test {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("aopsample03.xml");
        Math math = ctx.getBean("math", Math.class);
        int n1 = 100, n2 = 5;
        System.out.println("****************************** Add ******************************");
        math.add(n1, n2);
        System.out.println("");
        System.out.println("****************************** sub ******************************");

        math.sub(n1, n2);

        System.out.println("");
        System.out.println("****************************** pow ******************************");

        math.pow(n1 );


        StrUtil strUtil=ctx.getBean("strUtil",StrUtil.class);

        System.out.println("");
        System.out.println("****************************** strUtil ******************************");
        strUtil.show();



}

execution切点函数

execution():满足匹配模式字符串的所有目标类方法的连接点
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)

package com.ailianshuo.springaop.sample03;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
 *  通知类,横切逻辑
 * @author ailianshuo
 * 2017年7月25日 下午5:21:42
 * 
 */
@Component
@Aspect
public class Advices {
    @Before("execution(* com.ailianshuo.springaop.sample03.Math.*(..))")
    public void before(JoinPoint jp){
        System.out.println(jp.getSignature().getName());
        System.out.println("----------before advice----------");
    }

    /**
     * execution():满足匹配模式字符串的所有目标类方法的连接点
     * com.ailianshuo.springaop.sample03包下所有类的所有方法被切入
     * @param jp
    */ 
    @After("execution(* com.ailianshuo.springaop.sample03.*.*(..))")
    public void after_execution(JoinPoint jp){
        System.out.println("----------after execution advice----------");
    }



}

运行结果:

****************************** Add ******************************
add
----------before advice----------
10+5=15
----------after execution advice----------

****************************** sub ******************************
sub
----------before advice----------
10-5=5
----------after execution advice----------
****************************** pow ******************************
pow
----------before advice----------
10*10=100
----------after execution advice----------

****************************** strUtil ******************************
Hello StrUtil!
----------after execution advice----------

within切点函数

within():匹配指定的包的所有连接点,匹配目标对象拥有指定注解的类的所有方法

/**
     * within():匹配指定的包的所有连接点
     * com.ailianshuo.springaop.sample03包下所有类的所有方法被切入
     * @param jp
      */
    @After("within(com.ailianshuo.springaop.sample03.*)")
    public void after_within(JoinPoint jp){
        System.out.println("----------after within advice----------");
    }

运行结果:

****************************** Add ******************************
----------before advice----------
10+5=15
----------after within advice----------

****************************** sub ******************************
----------before advice----------
10-5=5
----------after within advice----------

****************************** pow ******************************
----------before advice----------
10*10=100
----------after within advice----------

****************************** strUtil ******************************
Hello StrUtil!
----------after within advice----------

this切点函数

匹配当前AOP代理对象类型的所有执行方法


    @After("this(com.ailianshuo.springaop.sample03.Math)")
    public void after_this_Math(JoinPoint jp){
        System.out.println("----------after this Math advice----------");
    }


    @After("this(com.ailianshuo.springaop.sample03.StrUtil)")
    public void after_this_StrUtil(JoinPoint jp){
        System.out.println("----------after this StrUtil advice----------");
    }

运行结果:

****************************** Add ******************************
----------before advice----------
10+5=15
----------after this Math advice----------

****************************** sub ******************************
----------before advice----------
10-5=5
----------after this Math advice----------

****************************** pow ******************************
----------before advice----------
10*10=100
----------after this Math advice----------

****************************** strUtil ******************************
Hello StrUtil!
----------after this StrUtil advice----------

args切点函数

@After("args(int,int)")
    public void after_args(JoinPoint jp){
        System.out.println("----------after args advice----------");
    }

运行结果

****************************** Add ******************************
----------before advice----------
10+5=15
----------after args advice----------

****************************** sub ******************************
----------before advice----------
10-5=5
----------after args advice----------

****************************** pow ******************************
----------before advice----------
10*10=100

****************************** strUtil ******************************
Hello StrUtil!

annotation切点函数

任何标注了指定注解的目标方法链接点

先自定义一个可以注解在方法上的注解

package com.ailianshuo.springaop.sample03;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** 
 * @author ailianshuo
 * 2017年7月26日 上午10:45:17
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnno {

}

Advices.java

/**
     * 
     * @annotation切点函数
     * @annotation():任何标注了指定注解的目标方法链接点
     * 要求方法必须被注解com.ailianshuo.springaop.sample03.MyAnno才会被织入横切逻辑
     * @param jp
    */
    @After("@annotation(com.ailianshuo.springaop.sample03.MyAnno)")
    public void after_annotation(JoinPoint jp){
        System.out.println("----------after annotation advice----------");
    }

StrUtil .java

 @MyAnno
    public void showAnno(){
        System.out.println("Hello MyAnno StrUtil!");
    }

运行结果:

****************************** Add ******************************
----------before advice----------
10+5=15

****************************** sub ******************************
----------before advice----------
10-5=5

****************************** pow ******************************
----------before advice----------
10*10=100

****************************** strUtil ******************************
Hello StrUtil!

****************************** showAnno ******************************
Hello MyAnno StrUtil!
----------after annotation advice----------

项目下载

请到码云:下载

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值