@Around简单使用示例——SpringAOP增强处理

£神魔★判官ぃ 2023-10-01 08:44 142阅读 0赞

@Around的作用

  • 既可以在目标方法之前织入增强动作,也可以在执行目标方法之后织入增强动作;
  • 可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标目标方法的执行;
  • 可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值; 当需要改变目标方法的返回值时,只能使用Around方法;

    • 虽然Around功能强大,但通常需要在线程安全的环境下使用。因此,如果使用普通的Before、AfterReturing增强方法就可以解决的事情,就没有必要使用Around增强处理了。

注解方式:如果需要对某一方法进行增强,只需要在相应的方法上添加上自定义注解即可

  1. package com.rq.aop.common.advice;
  2. import com.rq.aop.common.annotation.MyAnnotation;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.Around;
  5. import org.aspectj.lang.annotation.Aspect;
  6. import org.springframework.stereotype.Component;
  7. @Aspect //标注增强处理类(切面类)
  8. @Component //交由Spring容器管理
  9. public class AnnotationAspect {
  10. /*
  11. 可自定义切点位置,针对不同切点,方法上的@Around()可以这样写ex:@Around(value = "methodPointcut() && args(..)")
  12. @Pointcut(value = "@annotation(com.rq.aop.common.annotation.MyAnnotation)")
  13. public void methodPointcut(){}
  14. @Pointcut(value = "@annotation(com.rq.aop.common.annotation.MyAnnotation2)")
  15. public void methodPointcut2(){}
  16. */
  17. //定义增强,pointcut连接点使用@annotation(xxx)进行定义
  18. @Around(value = "@annotation(around)") //around 与 下面参数名around对应
  19. public void processAuthority(ProceedingJoinPoint point,MyAnnotation around) throws Throwable{
  20. System.out.println("ANNOTATION welcome");
  21. System.out.println("ANNOTATION 调用方法:"+ around.methodName());
  22. System.out.println("ANNOTATION 调用类:" + point.getSignature().getDeclaringTypeName());
  23. System.out.println("ANNOTATION 调用类名" + point.getSignature().getDeclaringType().getSimpleName());
  24. point.proceed(); //调用目标方法
  25. System.out.println("ANNOTATION login success");
  26. }
  27. }

注解类

  1. package com.rq.aop.common.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Retention(RetentionPolicy.RUNTIME)//运行时有效
  7. @Target(ElementType.METHOD)//作用于方法
  8. public @interface MyAnnotation {
  9. String methodName () default "";
  10. }

Controller

  1. package com.rq.aop.controller;
  2. import com.rq.aop.common.annotation.MyAnnotation;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.PathVariable;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. @Controller
  7. @RequestMapping("/hello")
  8. public class HelloController {
  9. @RequestMapping("/login/{name}")
  10. @MyAnnotation(methodName = "login")
  11. public void login(@PathVariable String name){
  12. System.out.println("hello!"+name);
  13. }
  14. }

运行结果:
在这里插入图片描述

匹配方法执行连接点方式

  1. package com.rq.aop.common.advice;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.Around;
  4. import org.aspectj.lang.annotation.Aspect;
  5. import org.springframework.core.annotation.Order;
  6. import org.springframework.stereotype.Component;
  7. @Aspect
  8. @Component
  9. @Order(0) //设置优先级,值越低优先级越高
  10. public class ExecutionAspect {
  11. @Around(value = "execution(* com.rq.aop.controller..*.*(..))")
  12. public void processAuthority (ProceedingJoinPoint point)throws Throwable{
  13. System.out.println("EXECUTION welcome");
  14. System.out.println("EXECUTION 调用方法:" + point.getSignature().getName());
  15. System.out.println("EXECUTION 目标对象:" + point.getTarget());
  16. System.out.println("EXECUTION 首个参数:" + point.getArgs()[0]);
  17. point.proceed();
  18. System.out.println("EXECUTION success");
  19. }
  20. }

eg.

  • 任意公共方法的执行:execution(public * *(…))
  • 任何一个以“set”开始的方法的执行:execution(* set*(…))
  • AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.*(…))
  • 定义在service包里的任意方法的执行: execution(* com.xyz.service..(…))
  • 定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.xyz.service….(…))

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

  • 定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:execution(com.test.spring.aop.pointcutexp…JoinPointObjP2.(…))”)
  • pointcutexp包里的任意类: within(com.test.spring.aop.pointcutexp.*)
  • pointcutexp包和所有子包里的任意类:within(com.test.spring.aop.pointcutexp…*)
  • 实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:this(com.test.spring.aop.pointcutexp.Intf)
  • 当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型
  • 带有@Transactional标注的所有类的任意方法: @within(org.springframework.transaction.annotation.Transactional) @target(org.springframework.transaction.annotation.Transactional)
  • 带有@Transactional标注的任意方法:
    @annotation(org.springframework.transaction.annotation.Transactional)
    @within和@target针对类的注解,@annotation是针对方法的注解
  • 参数带有@Transactional标注的方法:@args(org.springframework.transaction.annotation.Transactional)
  • 参数为String类型(运行是决定)的方法: args(String)
    运行结果:
  • 在这里插入图片描述

    切面执行顺序:
    在这里插入图片描述
    异常:
    在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,142人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringAOP使用总结

    一、AOP切面的方式 1.很多时候我们需要对一层进行切面,例如我们要对系统的Controler层进行切面,但是关于登陆和注册的Controller则放开;书写方式如下,切