• springboot 点滴(2)springboot AOP


    Spring是一个开源,轻量化,具有IOC和AOP两大核心功能的容器型框架。
    Spring Boot是简化新Spring应用的初始搭建以及开发过程。
    下面介绍一下Spring Boot AOP。

    1 AOP简介

    AOP: 面向切面编程。
    OOP: 面向对象编程。

    AOP是OOP:的补充,
    作用
    在不改变原有业务逻辑情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。

    场景:
    增加日志、权限处理。

    2 springboot AOP简介

    springboot 只支持方法类型的连接点

    术语:
    Joinpoint(连接点):
    连接点就是切入Bean中的某个方法的调用;

    PointCut(切入点):
    切入Bean中的要切入的方法;切点一定是连接点。

    Advice(通知/增强):
    通知是切入点注入的代码。

    Aspect(切面):
    是切入点和通知的结合。

    引入(Introduction)
    允许我们向现有的类中添加新方法或者属性。

    织入(Weaving)
    是把切面应用到目标对象并创建新的代理对象的过程,分为编译期织入、类加载期织入和运行期织入。

    通知有五种类型,分别是:
    1)前置通知(@Before):在目标方法调用之前调用通知
    2)后置通知(@After):在目标方法完成之后调用通知
    3)环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
    4)返回通知(@AfterReturning):在目标方法成功执行之后调用通知
    5)异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知

    3 springboot AOP示例:

    第1步:引入POM文件:

    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-aopartifactId>
    			<version>2.7.5version>
    		dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第2步:定义要切入的类AopController;

    @RestController
    @RequestMapping(value = "/aop")
    public class AopController {
    
        @RequestMapping(value = "/hello", method = RequestMethod.GET)
        public String sayHello(){
          System.out.println("springboot AOP 切点函数执行!");
          return "springboot AOP示例!";
        }
    
        @RequestMapping(value = "/error", method = RequestMethod.GET)
        public String printError(){
            float ret = 1/0;
            return "springboot AOP切点异常函数执行示例!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第3步:定义切面类AopAdvice;
    @Component 注解,把切面类AopAdvice作为bean引入容器中;
    @Aspect 注解,使AopAdvice成为切面类;

    @Aspect
    @Component
    @Slf4j
    public class AopAdvice {
    
        //切点
        @Pointcut("execution (* org.feidao.chapter02.controller.*.*(..))")
        public void testPointCut(){
    
        }
    
        //前置通知
        @Before("testPointCut()")
        public void beforeAdvice(JoinPoint jp){
            System.out.println("---前置通知  begin---");
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            // 记录下请求内容
            System.out.println("请求URL:" + request.getRequestURL().toString());
            System.out.println("请求http方式:" + request.getMethod());
            System.out.println("切点函数:" + jp);
            System.out.println("切点函数的参数 : " + Arrays.toString(jp.getArgs()));
            System.out.println("---前置通知  end---");
        }
    
        //后置通知
        @After("testPointCut()")
        public void afterAdvice(JoinPoint jp){
            System.out.println("---后置通知  begin---");
            System.out.println("---后置通知  end---");
        }
    
        //环绕通知
        @Around("testPointCut()")
        public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
            System.out.println("---环绕通知  begin---");
            try{
                proceedingJoinPoint.proceed();
            }catch (Throwable e){
                e.printStackTrace();
            }
            System.out.println("---环绕通知  end---");
        }
    
        //返回通知
        @AfterReturning(returning = "ret", pointcut = "testPointCut()")
        public void returnAdvice(String ret) throws Throwable {
            System.out.println("---返回通知  begin---");
            // 处理完请求,返回内容
            System.out.println("返回通知:方法的返回值 : " + ret);
            System.out.println("---返回通知  end---");
        }
    
        //异常通知
        @AfterThrowing(throwing = "ex", pointcut = "testPointCut()")
        public void exceptionAdvice(JoinPoint jp,Exception ex){
            System.out.println("---异常通知  begin---");
            System.out.println("产生异常的方法:"+jp);
            System.out.println("异常种类:"+ex);
            System.out.println("---异常通知  end---");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    最后验证:
    Postman请求正常的url:127.0.0.1:8080/aop/hello;

    ---环绕通知  begin---
    ---前置通知  begin---
    请求URL:http://127.0.0.1:8080/aop/hello
    请求http方式:GET
    切点函数:execution(String org.feidao.chapter02.controller.AopController.sayHello())
    切点函数的参数 : []
    ---前置通知  end---
    springboot AOP 切点函数执行!
    ---返回通知  begin---
    返回通知:方法的返回值 : springboot AOP示例!
    ---返回通知  end---
    ---后置通知  begin---
    ---后置通知  end---
    ---环绕通知  end---
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可见正常切点函数通知的执行过程。

    Postman请求异常的url:127.0.0.1:8080/aop/error;

    ---环绕通知  begin---
    ---前置通知  begin---
    请求URL:http://127.0.0.1:8080/aop/error
    请求http方式:GET
    切点函数:execution(String org.feidao.chapter02.controller.AopController.printError())
    切点函数的参数 : []
    ---前置通知  end---
    ---异常通知  begin---
    产生异常的方法:execution(String org.feidao.chapter02.controller.AopController.printError())
    异常种类:java.lang.ArithmeticException: / by zero
    ---异常通知  end---
    ---后置通知  begin---
    ---后置通知  end---
    ---环绕通知  end---
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可见异常切点函数通知的执行过程。

  • 相关阅读:
    图解系列 图解Kafka之Producer
    【大学复健】常用排序算法的原理与代码
    ubuntu 18.04 双系统安装
    计算机网络-网络文件共享协议
    Vue - Element el-table 行的展开与折叠
    基于FPGA的数据采集系统
    VUE3.0+Antdv+Asp.net WebApi开发学生信息管理系统(三)
    shell和ansible自动化运维实例
    Linux界的老古董
    springboot+新冠疫苗预约管理系统 毕业设计-附源码241530
  • 原文地址:https://blog.csdn.net/afei8080/article/details/127714468