继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Spring基础使用(六)-------AOP切面表达式

道可
关注TA
已关注
手记 47
粉丝 1万
获赞 1426
1. expression表达式

expression表达式分为三部分:指示器,通配符和操作符。

指示器
  • 匹配方法:execution()
  • 匹配注解:@target(),@args(),@within(),@annotation()
  • 匹配包/类型:within()
  • 匹配对象:this(),bean(),target()
  • 匹配参数:args()
通配符
  • *:匹配任意数量的字符
  • +:匹配指定类及其子类
  • ..:匹配任意数量的子包或者参数
运算符
  • &&:与
  • ||:或
  • !:非
2. 示例
匹配方法:execution()

execution()匹配方式使用的较为广泛,其格式如下图所示,其中修饰符和异常可以省略。

图片描述

    @Pointcut("execution(public * studySpring.service.LearnServiceImpl.get*(..))")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }
注解匹配:@target(),@args(),@within(),@annotation()

@annotation()可以单独进行使用,其他三种注解,需要指定包或者类。

1. @annotation()匹配标注有指定注解的方法。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation
{
}
    // 使用新注解修饰方法
    @MyAnnotation
    public void learn(String arg)
    {
        System.out.println("enter function learn");
        System.out.println("学习课程:" + arg);
        daoImpl.save(arg);
    }
    // 定义Pointcut,指定注解匹配方法
    @Pointcut("@annotation(studySpring.annotation.MyAnnotation)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }

2. @target()和@within()匹配标注有指定注解的类中的方法。

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface TargetWith
    {
    }
    @Component
    @TargetWith
    public class LearnServiceImpl implements ServiceInterface
    {
        ...
    }
    // 定义Pointcut,匹配指定注解的类中的所有方法
    @Pointcut("@target(studySpring.annotation.TargetWith) && within(studySpring.service..*)")
    // @Pointcut("@within(studySpring.annotation.TargetWith) && within(studySpring.service..*)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }

3. 当使用@args()注解修饰类的时候,对于只用该类作为参数的方法,被拦截。

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface TargetWith
    {
    }
    @Component
    @MyArgsAnnotation
    public class Item
    {
        public String name;
        public int grade;
        ...
    }
    // 定义Pointcut,匹配注解修饰的类作为参数的方法
    @Pointcut("@args(studySpring.annotation.MyArgsAnnotation) && within(studySpring.service..*)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }
匹配包/类型:within()

within主要用于匹配指定的类或者包及其子包下的所有方法。

    // 定义切入点
    @Pointcut("within(studySpring.service.LearnServiceImpl)")
    public void pointCut1(){}

    // 定义切入点
    @Pointcut("within(studySpring.service..*)")
    public void pointCut2(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }

    // 正常返回后通知
    @AfterReturning("pointCut2()")
    public void afterReturning()
    {
        System.out.println("AspectJDemo|afterReturning");
    }
对象匹配:this(),target(),bean()

this() 和 target()
的用法大体相同,主要作用有2点。第一,用于匹配实现指定接口的aop代理类;第二,匹配指定类的aop代理类。

bean() 用于匹配指定名称的bean。

1. 匹配实现指定接口的aop代理类(这里使用target和this都可以)

    // 匹配实现指定接口的aop代理类,这里使用target和this都可以。
    @Pointcut("target(studySpring.interfaces.ServiceInterface)")
    // @Pointcut("this(studySpring.interfaces.ServiceInterface)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }
@Component
public class LearnServiceImpl implements ServiceInterface
{
    public void learn(String arg)
    {
        System.out.println("enter function learn");
        System.out.println("学习课程:" + arg);
        daoImpl.save(arg);
    }
}
@Component
public class ShopServiceImpl implements ServiceInterface
{
    public void getList()
    {
        System.out.println("enter function ShopServiceImpl.getList()");
        System.out.println("黑凤梨");
        System.out.println("巧克力");
    }
}

2. 匹配指定类的aop代理类(使用target和this都可以)

    // 匹配指定类的aop代理类,这里使用target和this都可以。
    @Pointcut("target(studySpring.service.LearnServiceImpl)")
    // @Pointcut("this(studySpring.service.LearnServiceImpl)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }

3. bean() 用于匹配指定名称的bean

    // 匹配指定名称的bean:匹配名称中包含Service字符串的bean
    @Pointcut("bean(*Service*)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }
参数匹配:args()

用于匹配指定参数类型的方法,比如args(String)

还可以结合通配符使用,匹配第一个参数为String的方法:args(String,..)

但是args的匹配方法存在一个使用限制,无法单独使用,必须指定包或者类,否则程序异常。

    // 匹配第一个参数类型为String,而且在studySpring.service包中的方法。
    @Pointcut("args(String,..) && within(studySpring.service.*)")
    // 匹配参数类型为String,而且名称包含Service字段的bean中的方法。
    // @Pointcut("args(String) && bean(*Service*)")
    public void pointCut1(){}

    // 前置通知
    @Before("pointCut1()")
    public void before()
    {
        System.out.println("AspectJDemo|before");
    }
打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP