4.12 SpringBoot整合AOP ❤❤❤

这篇具有很好参考价值的文章主要介绍了4.12 SpringBoot整合AOP ❤❤❤。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. AOP简介

要介绍面向切面编程(Aspect-Oriented Programming,AOP),需要读者
首先考虑这样一个场景:
公司有一个人力资源管理系统目前已经上线,但是系统运行不稳定,有时运行得很慢,为了检测出到底是哪个环节出问题了,开发人员想要监控每一个方法的执行时间,再根据这些执行时间判断出问题所在。当问题解决后,再把这些监控移除掉
系统目前已经运行,如果手动修改系统中成千上万个方法,那么工作量未免太大,而且这些监控方法以后还要移除掉;如果能够在系统运行过程中动态添加代码,就能很好地解决这个需求
这种在系统运行时动态添加代码的方式称为面向切面编程(AOP)
Spring框架对AOP提供了很好的支持。在AOP中,有一些常见的概念需要读者了解。

  • Joinpoint(连接点): 类里面可以被增强的方法即为连接点。例如,想修改哪个方法的功能,那么该方法就是一个连接点。
  • Pointcut(切入点): 对Joinpoint进行拦截的定义即为切入点。例如,拦截所有以insert开始的方法,这个定义即为切入点。
  • Advice(通知): 拦截到Joinpoint之后所要做的事情就是通知。例如,上文说到的打印日志监控。通知分为前置通知、后置通知、异常通知、最终通知和环绕通知。
  • Aspect(切面):Pointcut和Advice的结合。
  • Target(目标对象):要增强的类称为Target。

2. SpringBoot支持

SpringBoot在Spring的基础上对AOP的配置提供了自动化配置解决方案spring-boot-starter-aop,使开发者能够更加便捷地在SpringBoot项目中使用AOP。
配置步骤如下。

2.1 AOP依赖

首先在SpringBootWeb项目中引入spring-boot-starter-aop依赖,代码如下:

        <!-- SpringBoot 拦截器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.2 定义切面

接下来创建切面,代码如下:

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

@Component
@Aspect
public class LogAspect1 {
    /**
     * 切入点为:com.ruoyi.system.service包下的所有类的所有方法
     */
    @Pointcut("execution(* com.ruoyi.system.service.*.* (..))")
    public void pc1() {
    }

    /**
     * 前置通知,对切入点pc1()进行增强
     *
     * @param jp 连接点:包含增强的方法信息
     */
    @Before(value = "pc1()")
    public void before(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println("Before 前置通知 >>" + name + "方法开始执行...");
    }

    /**
     * 后置通知,对切入点pc1()进行增强
     *
     * @param jp 连接点:包含增强的方法信息
     */
    @After(value = "pc1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println("After 后置通知 >>" + name + "方法结束执行...");
    }

    /**
     * 返回通知,对切入点pc1()进行增强
     *
     * @param jp     连接点:包含增强的方法信息
     * @param result 方法返回值
     */
    @AfterReturning(value = "pc1()", returning = "result")
    public void afterReturning(JoinPoint jp, Object result) {
        String name = jp.getSignature().getName();
        System.out.println("AfterReturning 返回通知 >>" + name + "方法返回值:" + result);
    }

    /**
     * 异常通知,对切入点pc1()进行增强
     *
     * @param jp 连接点:包含增强的方法信息
     * @param e  抛出的异常信息
     */
    @AfterThrowing(value = "pc1()", throwing = "e")
    public void afterReturning(JoinPoint jp, Exception e) {
        String name = jp.getSignature().getName();
        System.out.println("AfterThrowing 异常通知 >>" + name + "方法抛出异常,异常信息" + e.getMessage());
    }

    /**
     * 环绕通知
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("pc1()")
    public Object around(ProceedingJoinPoint pjp) {
        String name = pjp.getSignature().getName();
        System.out.println("Around 环绕通知 >>" + name + "方法开始执行...");
        try {
            return pjp.proceed();
        } catch (Throwable e) {
            System.out.println("Around 环绕通知 >>" + name + "方法发生异常...");
            throw new RuntimeException(e);
        } finally {
            System.out.println("Around 环绕通知 >>" + name + "方法结束执行...");
        }
    }

}

代码解释:

  • @Aspect注解表明这是一个切面类。
  • 第12~14行定义的pc1方法使用了@Pointcut注解,这是一个切入点定义。execution中的第一个*表示方法返回任意值,第二个*表示service包下的任意类,第三个*表示类中的任意方法,括号中的两个点表示方法参数任意,即这里描述的切入点为service包下所有类中的所有方法。
  • 第21~25行定义的方法使用了@Before注解,表示这是一个前置通知,该方法在目标方法执行之前执行。通过JoinPoint参数可以获取目标方法的方法名、修饰符等信息。
  • 第32~36行定义的方法使用了@After注解,表示这是一个后置通知,该方法在目标方法执行之后执行。
  • 第44~48行定义的方法使用了@AfterReturning注解,表示这是一个返回通知,在该方法中可以获取目标方法的返回值。@AfterReturning注解的returning参数是指返回值的变量名,对应方法的参数。注意,在方法参数中定义了result的类型为Object,表示目标方法的返回值可以是任意类型,若result参数的类型为Long,则该方法只能处理目标方法返回值为Long的情况。
  • 第56~60行定义的方法使用了@AfterThrowing注解,表示这是一个异常通知,即当目标方法发生异常时,该方法会被调用,异常类型为Exception表示所有的异常都会进入该方法中执行,若异常类型为ArithmeticException,则表示只有目标方法抛出的ArithmeticException异常才会进入该方法中处理。
  • 第69~81行定义的方法使用了@Around注解,表示这是一个环绕通知。环绕通知是所有通知里功能最为强大的通知,可以实现前置通知、后置通知、异常通知以及返回通知的功能。目标方法进入环绕通知后,通过调用ProceedingJoinPoint对象的proceed方法使目标方法继续执行,开发者可以在此修改目标方法的执行参数、返回值等,并且可以在此处理目标方法的异常。

配置完成
测试

17:17:35.368 [http-nio-8080-exec-1] INFO  o.a.c.c.C.[.[.[/] - [log,173] - Initializing Spring DispatcherServlet 'dispatcherServlet'
Around 环绕通知 >>selectUserList方法开始执行...
Before 前置通知 >>selectUserList方法开始执行...
17:17:35.623 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList_COUNT - [debug,135] - ==>  Preparing: SELECT count(0) FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id = d.dept_id WHERE u.del_flag = '0'
17:17:35.628 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList_COUNT - [debug,135] - ==> Parameters: 
17:17:35.630 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList_COUNT - [debug,135] - <==      Total: 1
17:17:35.633 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList - [debug,135] - ==>  Preparing: select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u left join sys_dept d on u.dept_id = d.dept_id where u.del_flag = '0' LIMIT ?
17:17:35.634 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList - [debug,135] - ==> Parameters: 10(Integer)
17:17:35.637 [http-nio-8080-exec-1] DEBUG c.r.s.m.S.selectUserList - [debug,135] - <==      Total: 2
AfterReturning 返回通知 >>selectUserList方法返回值:Page{count=true, pageNum=1, pageSize=10, startRow=0, endRow=10, total=2, pages=1, reasonable=true, pageSizeZero=false}
After 后置通知 >>selectUserList方法结束执行...
Around 环绕通知 >>selectUserList方法结束执行...

异常测试文章来源地址https://www.toymoban.com/news/detail-855805.html

Around 环绕通知 >>selectErr方法开始执行...
Before 前置通知 >>selectErr方法开始执行...
AfterThrowing 异常通知 >>selectErr方法抛出异常,异常信息null
After 后置通知 >>selectErr方法结束执行...
Around 环绕通知 >>selectErr方法发生异常...
Around 环绕通知 >>selectErr方法结束执行...
17:23:08.159 [http-nio-8080-exec-3] ERROR c.r.f.w.e.GlobalExceptionHandler - [handleRuntimeException,93] - 请求地址'/system/user/err',发生未知异常.
java.lang.RuntimeException: com.ruoyi.common.exception.ServiceException

**********************************************************

到了这里,关于4.12 SpringBoot整合AOP ❤❤❤的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Cloud实战案例 │ Apollo和Zuul的整合开发

    Apollo是携程研发的开源配置管理中心,能够集中管理应用于不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。 本案例结合一个案例介绍Apollo和Zuul的整合开发。整个应用分为4个微服务项目,分别是Eureka服务器项目mweath

    2024年02月14日
    浏览(26)
  • SpringBoot + Vue前后端分离项目实战 || 六:Jwt加密整合配置

    在之前的系统中,我们利用 UUID 配合 Redis 以达到角色登录的功能。 当前整个系统存在一个问题:人为 修改token值 后,用户仍然能在前端进行数据库操作,后台没有校验当前用户 token 就允许一些请求,导致系统存在 安全漏洞 。 解决方法: Jwt签名验证 。整合 Jwt 后,前端发

    2024年02月15日
    浏览(37)
  • Spring与Mybatis集成且Aop整合

    目录 一、集成 1.1 集成的概述 1.2 集成的优点 1.3 代码示例 二、整合 2.1 整合概述 2.2 整合进行分页 集成是指将不同的组件、部分或系统组合在一起,以形成一个整体功能完整的解决方案。它是通过连接、交互和协调组件之间的关系来实现的。 集成可以应用于各个领域,包括

    2024年02月11日
    浏览(25)
  • 【项目实战】一、Spring boot整合JWT、Vue案例展示用户鉴权

    【项目实战】Spring boot整合JWT、Vue案例展示用户鉴权 【微服务实战】JWT

    2024年02月09日
    浏览(36)
  • Springboot整合AOP实现日志的保存

    1.定义注解 2.编写切面的实现 3.测试

    2024年02月09日
    浏览(42)
  • 12、Spring之基于xml的AOP

    阅读本文前,建议先阅读Spring之基于注解的AOP 创建名为spring_aop_xml的新module,过程参考9.1节 12.2.1.1、定义前置通知的功能 12.2.1.2、配置前置通知到切面 12.2.1.3、测试使用效果 由控制台日志可知,切面类的前置通知(方法),通过切入点表达式,作用到了目标方法的连接点上

    2024年02月12日
    浏览(31)
  • MyBatis与Spring整合以及AOP和PageHelper分页插件整合

    目录 前言 一、MyBatis与Spring整合的好处以及两者之间的关系 1.好处 2.关系  二、MyBatis和Spring集成 1.导入pom.xml 2.编写配置文件  3.利用mybatis逆向工程生成模型层代码 三、常用注解  四、AOP整合pageHelper分页插件 创建一个切面 测试 MyBatis是一个开源的持久层框架,而Spring是一个

    2024年02月11日
    浏览(32)
  • Spring与MyBatis集成 AOP整合PageHelper插件

    目录 1.什么是集成? 2.Spring与MyBatis集成 3.Spring与MyBatis集成的基本配置 4.AOP整合PageHelper插件 集成是指将不同的组件、框架或系统整合到一起,使它们可以协同工作、相互调用、共享资源等。通过集成,可以实现不同组件之间的功能互补、数据交互、业务流程整合等。 在软件

    2024年02月10日
    浏览(33)
  • SpringBoot 整合redis + Aop防止重复提交 (简易)

    redis下载 解压 安装 看一下就会有  进入redis-6.0.8下的src目录 (  src 目录下有编译后的 redis 服务程序 redis-server,还有用于测试的客户端程序 redis-cli:) 然后启动 redis默认端口号 6379,建议更改。redis.conf是配置文件在  与src是同级目录。 要远程  #去掉保护模式,注释掉bi

    2024年02月12日
    浏览(31)
  • 7、SpringBoot2之整合事务及AOP

    本文在SpringBoot2之整合Mybatis的基础上进行 注意:只要引入 spring-boot-starter-jdbc 启动器(详见6.1节),spring boot 便会自动配置好 DataSourceTransactionManager ; 因此,只需在方法(或者类)加上 @Transactional 注解,即可进行事务管理。 测试前的数据 测试时发生异常 测试后的数据没变

    2024年02月03日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包