开发者

Springboot如何正确使用AOP问题

目录
  • ​一、AOP概念
  • 二、切点表达式​
    • execution表达式
    • 案例
  • 三、AOP通知
    • 四、springboot中使用AOP
      • 导出依赖
      • 自定义注解
      • 创建切面类
      • 自定义一个接口
      • 测试
    • 总结

      ​一、AOP概念

      切面(ASPect)

      • 一个关注点的模块化,这个关注点可能会横切多个对象。
      • 事务管理是J2EE应用中一个关于横切关注点的很好的例子。
      • 在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现

      编程客栈接点(JoinPoint)

      在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在SpringAOP中,一个连接点总是表示一个方法的执行

      通知(Advice)

      • 在切面的某个特定的连接点上执行的动作。
      • 其中包括了Around、Before和After等不同类型的通知。
      • 许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链

      切入点(PointCut)

      • 匹配连接点的断言。
      • 通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时),切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法

      引入(Intorduction)

      • 用来给一个类型声明额外的方法或属性(也被称为连接类型声明)。
      • Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。
      • 例如,你可以使用引入来使一个bean实现接口,以便简化缓存机制

      目标对象(Target Object)

      • 被一个或者多个切面所通知的对象。也被称做被通知对象。
      • 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理对象

      AOP代理(Aop proxy)

      • AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。
      • 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理

      植入(weaving)

      • 把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。
      • 这些可以在编译时(例如使用AspectJ编js译器),类加载时和运行时完成。
      • Spring和其他纯Java AOP框架一样,在运行时完成织入

      二、切点表达式​

      execution表达式

      用于匹配方法执行的连接点,属于方法级别

      语法:

      execution(修饰符 返回值类型 方法名(参数)异常)

      语法参数描述
      修饰符可选,如public,protected,写在返回值前,任意修饰符填*号就可以
      返回值类型必选,可以使用*来代表任意返回值
      方法名必选,可以用*来代表任意方法
      参数()代表是没有参数,(..)代表是匹配任意数量,任意类型的参数,当然也可以指定类型的参数进行匹配,如要接受一个String类型的参数,则(java.lang.String), 任意数量的String类型参数:(java.lang.String..)
      异常可选,语法:throws 异常,异常是完整带包名,可以是多个,用逗号分隔

      符号:

      符号描述
      *匹配任意字符
      匹配多个包或者多个参数
      +表示类及其子类

      条件符:

      符号描述
      &&、and
      ||
      !

      案例

      拦截com.gj.web包下的所有子包里的任意类的任意方法

      execution(* com.gj.web..*.*(..))
      

      拦截com.gj.web.api.Test2Controller下的任意方法

      execution(* com.gj.web.api.Test2Controller.*(..))
      

      拦截任何修饰符为public的方法

      execution(public * * (..))
      

      拦截com.gj.web下的所有子包里的以ok开头的方法

      execution(* com.gj.web..*.ok*(..))
      

      三、AOP通知

      在切面类中需要定义切面方法用于响应响应的目标方法,切面方法即为通知方法,通知方法需要用注解标识,AspectJ支持5种类型的通知注解

      注解描述
      @Before前置通知, 在方法执行之前执行
      @After后置通知, 在方法执行之后执行
      @AfterReturn返回通知, 在android方法返回结果之后执行
      @AfterThrowing异常通知, 在方法抛出异常之后
      @Around环绕通知,围绕方法的执行

      @Before

          @Before("testCut()")
          public void cutProcess(JoinPoint joinPoint) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP开始拦截, 当前拦截的方法名: " + method.getName());
          }
      

      @After

          @After("testCut()")
          public void after(JoinPoint joinPoint) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP执行的方法 :"+method.getName()+" 执行完了");
          }
      

      @AfterReturn:其中value表示切点方法,returning表示返回的结果放到result这个变量中

          /**
           * returning属性指定连接点方法返回的结果放置在result变量中
           * @param joinPoint 连接点
           * @param result 返回结果
           */
          @AfterReturning(value = "testCut()",returning = "result")
          public void afterReturn(JoinPoint joinPoint, Object result) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP拦截的方法执行成功, 进入返回通知拦截, 方法名为: "+method.getName()+", 返回结果为: "+result.toString());
          }
      

      @AfterThrowing:其中value表示切点方法,throwing表示异常放到e这个变量

          @AfterThrowing(value = "testCut()", throwing = "e")
          public void afterThrow(JoinPoint joinPoint, Exception e) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP进入方法异常拦截, 方法名为: " + method.getName() + ", 异常信息为: " + e.getMessage());
          }
      

      @Around

          @Around("testCut()")
          public Object testCutAround(ProceedingJoinPoint joinPoint) throws Throwable {
              System.out.println("注解方式AOP拦截开始进入环绕通知.......");
                  Object proceed = joinPoint.proceed();
                  System.out.println("准备退出环绕......");
                  return proceed;
          }
      

      四、springboot中使用AOP

      导出依赖

              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
      

      Springboot如何正确使用AOP问题

      自定义注解

      package com.hl.springbootrunner.aop;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.METHOD)
      public @interface AOPAnnotations {
      }
      

      创建切面类

      package com.hl.springbootrunner.aop;
      
      import org.aspectj.lang.JoinPoint;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.annotation.*;
      import org.aspectj.lang.reflect.MethodSignature;
      import org.springframework.stereotype.Component;
      
      import java.lang.reflect.Method;
      
      
      @Aspect
      @Component
      public class TestAspect {
      
          /**
           * 这里的路径填自定义注解的全路径
           */
          @Pointcut("@annotation(com.hl.springbootrunner.aop.AOPAnnotations)")
          public void testCut() {
      
          }
      
          @Before("testCut()")
          public void cutProcess(JoinPoint joinPoint) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP开始拦截, 当前拦截的方法名: " + method.getName());
          }
      
          @After("testCut()")
          public void after(JoinPoint joinPoint) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP执行的方法 :" + method.getName() + " 执行完了");
          }
      
      
          @Around("testCut()")
          public Ojsbject testCutAround(ProceedingJoinPoint joinPoint) throws Throwable {
              System.out.println("注解方式AOP拦截开始进入环绕通知.......");
              Object proceed = joinPoint.proceed();
              System.out.println("准备退出环绕......");
              return proceed;
          }
      
          /**
           * returning属性指定连接点方法返回的结果放置在result变量中
           *
           * @param joinPoint 连接点
           * @param result    返回结果
           */
          @AfterReturning(value = "testCut()", returning = "result")
          public void afterReturn(JoinPoint joinPoint, Object result) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP拦截的方法执行成功, 进入返回通知拦截, 方法名为: " + method.getName() + ", 返回结果为: " + result.toString());
          }
      
          @AfterThrowing(value = "testCut()", throwing = "e")
          public void afterThrow(JoinPoint joinPoint, Exception e) {
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              System.out.println("注解方式AOP进入方法异常拦截, 方法名为: " + method.getName() + ", 异常信息为: " + e.getMessage());
          }
      
      }
      php

      自定义一个接口

      @RestController
      public class TestController {
       
          @GetMapping("/ok")
          @AOPAnnotations
          public String test2() {
              return "ok";
          }
       
      }
      

      测试

      Springboot如何正确使用AOP问题

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜