Springboot AOP切面

news2024/11/23 21:52:51

文章目录

  • SpringBoot Aop
    • 切面(Aop)
      • 一、什么是切面
      • 二、切面的用途
      • 三、AOP切面常用注解
      • 四、详细内容
        • 1、切面(Aspect)
        • 2、连接点(Joinpoint)
        • 3、通知(Advice)
        • 4.切入点(Pointcut)
      • 五、代码操作
        • Maven依赖
        • 1、定义一个切面类
        • 2、在需要切面的方法上加入@Pointcut注解
        • 3、指定切面方法之前 @Before
        • 4、在指定方法之后做什么@After
        • 5、数据增强处理@AfterReturning
        • 6、数据异常处理@AfterThrowing
      • 六、Aspect切面类完整示例
      • 七、切面实际业务实现 —— 拦截功能
        • (一)基于注解拦截
          • 1、引入Maven依赖
          • 2、定义拦截注解 @InterceptAnnotation
          • 3、定义切面类及方法
        • (二)基于表达式拦截
          • 1、定义切面类
          • 2、切点多个表达式或注解示例
        • (三)测试
          • 1、基于表达式测试
          • 2、接口加注解
          • 3、通过`@Order`注解规定切面类执行顺序
      • 八、定义切面步骤总结

SpringBoot Aop

切面(Aop)

一、什么是切面

AOP(Aspect OrientedProgramming):面向切面编程,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

二、切面的用途

日志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理。

三、AOP切面常用注解

在这里插入图片描述

四、详细内容

在这里插入图片描述

1、切面(Aspect)

2、连接点(Joinpoint)

程序执行过程中的某一行为动作,例如,某一个方法的调用或者抛出异常等行为。

3、通知(Advice)

“切面”对于某个“连接点”所产生的动作。比如,切面类对项目中service包下的所有类的方法进行日志记录的动作就是一个Advice。一个切面可以包含多个Advice:

  1. 前置通知:在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。注解中使用@Before声明。
  2. 后通知:当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。注解中使用@After声明。
  3. 返回后通知:在某连接点正常完成后执行的通知,不包括抛出异常的情况。注解中使用@AfterReturning声明。
  4. 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行。注解中使用@Around声明。
  5. 抛出异常后通知: 在方法抛出异常退出时执行的通知。注解中使用@AfterThrowing声明。

通知执行顺序:

前置通知 → 环绕通知连接点之前 → 连接点执行 → 环绕通知连接点之后 → 返回通知 → 后通知 → (如果发生异常)异常通知 → 后通知。

4.切入点(Pointcut)

匹配连接点的断言,在AOP中通知和一个切入点表达式关联。

五、代码操作

Maven依赖

<!--        切面依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

1、定义一个切面类

在这里插入图片描述

2、在需要切面的方法上加入@Pointcut注解

@Pointcut使用有两种

  1. 方式一:execution()
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopAspect {

    /**
     *  @Pointcut:定义一个切面,所关注的某件事入口
     *  execution():表达式主体
     *  第一个 *:表示返回值类型, *表示所有类型
     *  com.sapphire.common.service:包名
     *  ..:表示当前包和当前包子包
     *  第二个*:表示类名,*表示所有类
     *  *(..):*表示方法名,括弧里边表示参数,..表示任何参数
     */
    @Pointcut("execution(* com.sapphire.common.service..*.*(..))")
    public void pointCut(){
    
//        业务逻辑

    }
}
  1. 方式二: @annotation()
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopAspect {

    /**
     * @annotation():针对否个注解来定义切面,如下根据@GetMapping进行切面 比如:@GetMapping、@PostMapping、@DeleteMapping
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void pointCut() {
//        业务逻辑
    }
}

3、指定切面方法之前 @Before

import org.aspectj.lang.annotation.Before;

/**
     *  @Before:在之前做什么,指定的方法在切面切入目标方法之前执行
     *  pointcut():定义切面入口方法
     */
    @Before("pointCut()")
    public void before(){
//        业务逻辑
    }

4、在指定方法之后做什么@After

import org.aspectj.lang.annotation.After;

 /**
     *   @After:指定的方法在切面切入目标方法之后执行、和@Before注解对应
     *   pointcut():定义切面入口方法
     */
    @After("pointCut()")
    public void after(){
//        业务逻辑
    }

5、数据增强处理@AfterReturning

/**
     * @AfterReturning :和 `@After` 有些类似,区别在于 `@AfterReturning` 注解可以用来捕获切入方法执行完之后的返回值,对返回值进行业务逻辑上的增强处理
     * pointcut:切面方法名
     * returning:被切方法的返回值,必须要和参数保持一致,否则会检测不到
     */
    @AfterReturning(pointcut = "pointCut()", returning = "result")
    public void afterReturning(String result) {
//        业务逻辑
    }

6、数据异常处理@AfterThrowing

 /**
     * @AfterThrowing:被切方法执行时抛出异常时会进入 
     * pointcut:切面方法名
     * throwing:属性的值必须要和参数一致
     */
    @AfterThrowing(pointcut = "pointCut()", throwing = "ex")
    public void afterThrowing(Throwable ex) {
//        业务处理
    }

六、Aspect切面类完整示例

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopAspect {

    /**
     * @annotation():针对否个注解来定义切面,如下根据@GetMapping进行切面 比如:@GetMapping、@PostMapping、@DeleteMapping
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void pointCut() {
        System.out.println("@Pointcut:定义一个切面,所关注的某件事入口\n");
    }

    /**
     *  @Before:在之前做什么,指定的方法在切面切入目标方法之前执行
     *  pointcut():定义切面入口方法
     */
    @Before("pointCut()")
    public void before(){
//        业务逻辑
    }

    /**
     *   @After:指定的方法在切面切入目标方法之后执行、和@Before注解对应
     *   pointcut():定义切面入口方法
     */
    @After("pointCut()")
    public void after(){
//        业务逻辑
    }


    /**
     * @AfterReturning :和 `@After` 有些类似,区别在于 `@AfterReturning` 注解可以用来捕获切入方法执行完之后的返回值,对返回值进行业务逻辑上的增强处理
     * pointcut:切面方法名
     * returning:被切方法的返回值,必须要和参数保持一致,否则会检测不到
     */
    @AfterReturning(pointcut = "pointCut()", returning = "result")
    public void afterReturning(String result) {
//        业务逻辑
    }

    /**
     * @AfterThrowing:被切方法执行时抛出异常时会进入
     * pointcut:切面方法名
     * throwing:属性的值必须要和参数一致
     */
    @AfterThrowing(pointcut = "pointCut()", throwing = "ex")
    public void afterThrowing(Throwable ex) {
//        业务处理
    }
}

七、切面实际业务实现 —— 拦截功能

(一)基于注解拦截

1、引入Maven依赖
<!--        web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
<!--        切面依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
2、定义拦截注解 @InterceptAnnotation
package com.sapphire.common.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterceptAnnotation {

}

附加:关于自定义注解,参考如下链接

Java自定义注解

3、定义切面类及方法
package com.sapphire.common.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class InterceptAnnotationAspect {

    @Pointcut("@annotation(com.sapphire.common.annotation.InterceptAnnotation)")
    public void interceptPointcut(){

    }

    @Around("interceptPointcut()")
    public Object interceptAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("基于注解拦截的切面类");
        return joinPoint.proceed();
    }
}

其中joinPoint.proceed()执行目标方法,如果没有调用,则不执行目标方法

proceed传参数的方法可以动态的改变传入目标方法的参数:

在这里插入图片描述

(二)基于表达式拦截

表达式:* com.sapphire.common.controller..*.*(..)
1、定义切面类
package com.sapphire.common.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class InterceptControllerAspect {

    @Pointcut("execution(* com.sapphire.common.controller..*.*(..))")
    public void controllerIntercept(){

    }


    @Around("controllerIntercept()")
    public Object controllerInterceptAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("基于表达式进行拦截切面类");
        return joinPoint.proceed();
    }
}
2、切点多个表达式或注解示例
 @Pointcut("execution(* com.example.demo.controller..*.*(..))||@annotation(com.example.demo.anot.PermissionAnnotation)")

(三)测试

1、基于表达式测试

在这里插入图片描述

控制台打印结果:

此时执行了基于表达式的切面类中的方法。
在这里插入图片描述

2、接口加注解

在这里插入图片描述

控制台打印结果:

在这里插入图片描述

3、通过@Order注解规定切面类执行顺序

上图控制台打印结果可以看到先执行了注解切面类然后执行表达式切面类,现实中,可以通过@Order(0)注解规定切面类执行顺序,数字越小,执行越靠前

如下图所示:
在这里插入图片描述
测试结果:

表达式切面类先于注解切面类执行。
在这里插入图片描述

八、定义切面步骤总结

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PMP是什么?PMP证书有什么用?(含PMP资料)

PMP介绍 PMP的英文全称是Project Management Professional&#xff0c;中文全称叫做项目管理专业人士资格认证。 它是由美国项目管理协会(PMI)在全球范围内推出的针对项目经理的资格认证体系&#xff0c;严格评估项目管理人员知识技能是否具有高品质的资格认证考试&#xff0…

学习:如何使用Axure制作网站、app结构图

​“老师&#xff0c;axure里面可以制作网站的结构图吗&#xff1f;” “结构图只能在脑图工具中才能画吗&#xff1f;能不能直接在axure里面直接画&#xff1f;” “结构图到底需不需要做&#xff1f;对我来说好像没什么用呢” 在同学们的学习当中&#xff0c;有部分同学对…

CIO你好,现在是时候我们来谈一下“去”中台的问题了

去中台是个什么鬼 去中台&#xff1f;要不我去XXXXXXX 首先&#xff0c;你看到这个标题有没有懵圈&#xff1f;是不是有一种。。。 的感觉&#xff1f; 不过我现在告诉你&#xff0c;你没有看错。这篇文章是正儿八经的来谈“去”中台的。只不过这个“去”字&#xff0c;打着…

数据结构(链表)

链表及其实现 链式结构 顺序表插入、删除时间代价的分析&#xff0c;可以看出其时间复杂度是线性阶的&#xff0c;而且会引起大量已存储元素的位置移动。 改进方法&#xff1a;链式结构 各个元素的物理存放位置在存储器中是任意的&#xff0c;不一定连续。每个元素放在一个独…

国产新冠口服药重大突破:疗效不劣于Paxlovid,且安全性更高

*仅供医学专业人士阅读参考最近一段时间&#xff0c;新型冠状病毒感染&#xff08;Covid-19&#xff09;人数的激增&#xff0c;让全国多地迎来了重症“冲击波”&#xff0c;医疗卫生系统承受着极大的压力。 在新冠治疗药物方面&#xff0c;我国当前情况如何&#xff1f;最近Pa…

opencv鱼眼镜头矫正

说明 鱼眼镜头是一种视场角很大的镜头&#xff0c;但是得到的图片有很大的畸变&#xff0c;所以需要对鱼眼镜头进行标定&#xff0c;标定所得的参数可以对鱼眼镜头的图像进行矫正。 下图来自opencv的文档。其中c是鱼眼镜头原图&#xff0c;a和b是不同的矫正方法得到的图片。 …

K8S部署Apollo配置中心

K8S部署Apollo配置中心 参考文档: https://github.com/apolloconfig/apollo/tree/v1.8.0 [K8S部署apollo配置中心](https://www.cnblogs.com/Fengyinyong/p/14903725.html)[apollo官网文档](https://www.apolloconfig.com/#/zh/README)1、错误问题记录 在k8s里面部署时也遇到…

UDS-11.2 ReadDataByIdentifier (22) service

11.2.1 服务描述 来自&#xff1a;ISO 14229-1-2020.pdf ReadDataByIdentifier服务允许客户端从由一个或多个dataidentifier标识的服务器请求数据记录值。 客户端请求消息包含一个或多个两个字节的dataIdentifier值&#xff0c;用于标识由服务器维护的数据记录(关于允许的dataI…

【监督-非监督组合:全色锐化】

Supervised-unsupervised combined deep convolutional neural networks for high-fidelity pansharpening &#xff08;监督-非监督组合深度卷积神经网络实现高保真全色锐化&#xff09; 深度学习全色锐化方法因其优异的性能成为近年来的研究热点&#xff0c;基于Wald协议的卷…

GBASE合芯科技打造“国产芯片+数据库”国产替代解决方案

数据库的重要性 数据库是国产化基础软件的重要部分&#xff0c;是信息系统的核心。我国信息技术软硬件底层标准、架构、产品、以及生态体系被外国把控&#xff0c;这些上游核心技术遭遇限制严重影响了我国关键科技和产业的发展。2018年&#xff0c;中兴通讯被列入美国实体清单…

2022/12/29总结

今天AC了一道题目&#xff1a; P1825 [USACO11OPEN]Corn Maze S (1条消息) P1825 [USACO11OPEN]Corn Maze S_lxh0113的博客-CSDN博客 然后下面是学到的知识&#xff1a; 之前学习算法的时候总是牵扯到图&#xff0c;但是关于图的一些知识并没有了解。下面是有关图的基础知识…

区块链技术的官方材料整理

引自&#xff1a;区块链白皮书&#xff08;2018年&#xff09;、区块链白皮书&#xff08;2020年&#xff09;、中国区块链技术和应用发展白皮书、可信区块链赋能数字政府应用指南 区块链的概念 定义&#xff1a;区块链&#xff08;Blockchain&#xff09;是一种由多方共同维…

如何在 SwiftUI macOS 应用程序中显示和隐藏边栏

用户可以通过在边缘周围拖动来调整侧边栏的大小。 如果他们将它拖得足够远,侧边栏将关闭,并且无法将其设置回来。 本文将告诉您如何通过添加其他选项来显示和隐藏边栏来缓解此问题。 侧边栏一旦折叠,就无法恢复。 拖动左边缘会调整窗口大小,而不是将侧边栏带回来。 有两种…

力扣 1764. 通过连接另一个数组的子数组得到一个数组

题目 给你一个长度为 n 的二维整数数组 groups &#xff0c;同时给你一个整数数组 nums 。 你是否可以从 nums 中选出 n 个 不相交 的子数组&#xff0c;使得第 i 个子数组与 groups[i] &#xff08;下标从 0 开始&#xff09;完全相同&#xff0c;且如果 i > 0 &#xff…

【大型电商项目开发】订单功能实现(拦截器、feign丢失请求头、接口幂等性)-55

一&#xff1a;订单概念 1.1 订单中心 电商系统涉及到 3 流&#xff0c;分别时信息流&#xff0c;资金流&#xff0c;物流&#xff0c;而订单系统作为中枢将三者有机的集合起来。订单模块是电商系统的枢纽&#xff0c;在订单这个环节上需求获取多个模块的数据和信息&#xff0…

多线程问题(三)

目录 一、线程安全的单例模式 1、饿汉模式 2、懒汉模式 二、阻塞队列 三、定时器 1、标准库中定时器的使用用法 2、模拟实现定时器 a、首先需要创建出一个专门的类来表示schedule中的任务&#xff08;TimerTask&#xff09; b、使用合适的数据结构组织任务 c、…

Servlet基础教程 (保姆级教学)

Servlet基础教程一、Servlet 是什么二、第一个 Servlet 程序2.1 创建项目2.2 引入依赖2.3 创建目录2.4 编写代码2.5 打包程序2.6 部署程序2.7 验证程序三、更方便的部署方式3.1 安装 Smart Tomcat 插件3.2 配置 Smart Tomcat 插件四、常见的访问出错4.1 出现 4044.2 出现 4054.…

【jrebel and xrebel问题记录】激活时出现LS client not configued

教程目录问题描述所使用的环境和版本解决过程手动下载jrebel结束语问题描述 笔者在重装另一台电脑的时候又遇到了这个安装jrebel and xrebel进行激活的问题 但是我在网上找了很多的办法&#xff08;其实都是相同的办法&#xff0c;只是在尝试别人不同的用于激活的服务器&#…

【Java编程进阶】方法初识

推荐学习专栏&#xff1a;Java 编程进阶之路【从入门到精通】 文章目录1. Java 方法初识2. 方法的创建与使用3. 方法的分类3.1 无参无返回值3.2 无参带返回值3.3 有参无返回值3.4 有参带返回值4. 递归方法5. 总结1. Java 方法初识 方法是组合在一起来执行操作语句的集合&#…

k8s收集日志

k8s收集日志 一.收集控制台日志 采用fluentdeskibana来做 所需要的文件可以在这里找 https://github.com/kubernetes/kubernetes/tree/v1.23.0/cluster/addons/fluentd-elasticsearch1.创建目录并下载所需文件 cd /root/k8s/yaml/efk [rootworker1 efk]# ll total 44 -rw-…