基于注解的Spring AOP

基于注解的Spring AOP

  1. 常用的注解

    注解解释
    @Before该通知方法会在目标方法执行之前执行
    @AfterReturning该通知方法会在目标方法执行完返回后执行
    @After该通知方法会在目标方法返回或抛出异常后执行
    @Around该通知方法将目标方法封装起来,环绕通知
    @AfterThrowing该通知方法会在目标方法抛出异常后执行
    @Pointcut通用切入点
  2. @Pointcutexecution语法

    execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)

    带有?的模式可以省略掉
    多种语法可以使用&&、 ||、 !连接

  3. @Pointcut之其它语法

    语法解释
    execution用于匹配方法执行的连接点
    within用于匹配指定类型内的方法执行
    this用于匹配当前AOP代理对象类型的执行方法
    args用于匹配当前执行的方法传入的参数为指定类型的执行方法
    @within用于匹配所有持有指定注解类型类的方法(注解在类上)
    @annotation用于匹配当前执行方法持有指定注解的方法(注解在方法上)
  4. 代码示例
    完整代码示例

    package sky.jin.aspect.aspect;
    
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    import sky.jin.aspect.annotaion.UnknownException;
    
    /**
     * 切面
     *
     * @author sky.jin
     * @date 2022/2/7 15:35
     */
    @Slf4j
    @Aspect
    @Component
    public class MyAspect {
    
        /**
         * execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)
         *
         * - execution:用于匹配方法执行的连接点;
         * - within:用于匹配指定类型内的方法执行;
         * - this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口类型匹配;
         * - target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口类型匹配;
         * - args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
         * - @within:用于匹配所以持有指定注解类型内的方法;
         * - @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
         * - @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
         * - @annotation:用于匹配当前执行方法持有指定注解的方法;
         *
         */
        // 组合方式 &&、 ||、 !
        // 指定 aspect 包和子包的任意方法的执行
    //    @Pointcut(value = "execution(* sky.jin.aspect..*(..))")
        // 任意公共方法的执行
    //    @Pointcut(value = "execution(public * sky.jin.aspect..*(..))")
        // 任何一个以“queryNameBy”开始的方法的执行
    //    @Pointcut(value = "execution(* queryNameBy*(..))")
        // 指定 AspectService 接口的任意方法的执行
    //    @Pointcut(value = "execution(* sky..aspect.service.AspectService.*(..))")
        // 指定 service 包任意类方法的执行
    //    @Pointcut(value = "execution(* sky..aspect.service.*(..))")
        // 指定 service 包和子包任意类方法的执行
    //    @Pointcut(value = "execution(* sky..aspect.service..*(..))")
        // 指定 controller 包任意类方法的执行
    //    @Pointcut(value = "within(sky.jin.aspect.controller.*)")
        // 指定 aspect 包和子包任意类方法的执行
    //    @Pointcut(value = "within(sky.jin.aspect..*)")
        // 实现了AspectController接口的所有类,如果AspectController不是接口,限定AspectController单个类
    //    @Pointcut(value = "this(sky.jin.aspect.controller.AspectController)")
        // 实现了AspectService接口的所有类,如果AspectService不是接口,限定SAspectService单个类
    //    @Pointcut(value = "this(sky.jin.aspect.service.AspectService)")
        // 带有@UnknownException注解的所有类的任意方法
    //    @Pointcut(value = "@within(sky.jin.aspect.annotaion.UnknownException)")
        // 带有@UnknownException注解的所有类的任意方法 ×(没有调通)
    //    @Pointcut(value = "@target(sky.jin.aspect.annotaion.UnknownException)")
        // 带有@UnknownException注解的任意方法
    //    @Pointcut(value = "@annotation(sky.jin.aspect.annotaion.UnknownException)")
        // 参数带有@PathVariable注解的任意方法 ×(没有调通)
    //    @Pointcut(value = "@args(org.springframework.web.bind.annotation.PathVariable)")
        @Pointcut(value = "within(sky.jin.aspect..*) && args(Long, ..)") // 参数为String类型(运行时决定)的方法
        public void point(){}
    
        /**
         * 该通知方法会在目标方法执行之前执行
         */
        @Before(value = "point()", argNames = "jp")
        public void before(JoinPoint jp) {
            log.info("===> 前置通知 MyAfterThrowing before jp = {} params = {}", jp, jp.getArgs());
        }
    
        /**
         * 该通知方法会在目标方法执行完返回后执行
         */
        @AfterReturning("point()")
        public void afterReturning(JoinPoint jp) {
            log.info("===> 后置通知 MyAfterThrowing afterReturning jp = {} params = {}", jp, jp.getArgs());
        }
    
        /**
         * 通知方法会在目标方法返回或抛出异常后执行
         */
        @After("point()")
        public void after(JoinPoint jp) {
            log.info("===> 后置或异常通知 MyAfterThrowing after jp = {}", jp);
        }
    
        /**
         * 该通知方法将目标方法封装起来,环绕通知
         */
        @Around(value = "point()", argNames = "jp")
        public Object around(ProceedingJoinPoint jp) throws Throwable {
            log.info("===> 环绕通知开始 MyAfterThrowing around begin jp = {}", jp);
            Object proceed = jp.proceed();
            log.info("===> 环绕通知结束 MyAfterThrowing around end jp = {}", jp);
            return proceed;
        }
    
        /**
         * 该通知方法会在目标方法抛出异常后执行
         * - @annotation:用于匹配当前执行方法持有指定注解的方法
         */
        @AfterThrowing(throwing = "e", pointcut = "@annotation(unknownException)")
        public void afterThrowing_annotation(JoinPoint jp, Throwable e, UnknownException unknownException) {
            log.info("===> 异常通知 MyAfterThrowing afterThrowing_annotation jp = {} unknownException = {} ", jp, unknownException);
        }
    
        /**
         * 该通知方法会在目标方法抛出异常后执行
         */
        @AfterThrowing(throwing = "e", pointcut = "point()")
        public void AfterThrowing(JoinPoint jp, Throwable e) {
            log.info("===> 异常通知 MyAfterThrowing AfterThrowing jp = {}", jp);
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值