如皋建设局网站/seo顾问服务 乐云践新专家

如皋建设局网站,seo顾问服务 乐云践新专家,权威的南通网站建设,怎么设计海报图片文章目录 前言1. AOP基础1.1 AOP概述: 什么是AOP?1.2 AOP快速入门1.3 Spring AOP核心中的相关术语(面试)2. AOP进阶2.1 通知类型2.1.1 @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有)2.1.2 @Before:前置通知,此…

文章目录

  • 前言
  • 1. AOP基础
    • 1.1 AOP概述: 什么是AOP?
    • 1.2 AOP快速入门
    • 1.3 Spring AOP核心中的相关术语(面试)
  • 2. AOP进阶
    • 2.1 通知类型
      • 2.1.1 @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有)
      • 2.1.2 @Before:前置通知,此注解标注的通知方法在目标方法前被执行(通知的代码只放在业务方法之前)
      • 2.1.3 @AfterReturning : 后置(返回)通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行(通知的代码只放在业务方法之后)
      • 2.1.4 @After :后置最终通知,此注解标注的通知方法无论目标方法如何结束(正常返回或抛出异常),都会执行。(通知代码在 finally 的代码块之中)
      • 2.1.5 @AfterThrowing : 后置异常通知,此注解标注的通知方法在目标方法抛出异常后执行。(通知代码在捕获异常 catch(){}的代码块之中)
    • 2.2 通知顺序(如果多个切片类都操作一个目标方法会发生什么呢?)
      • 2.2.1 默认顺序规则
      • 2.2.2 使用Spring提供的@Order注解指定顺序规则
    • 2.3 切入点表达式
      • 2.3.1 execution
      • 2.3.2 @annotation(更灵活简单)
      • 2.3.3 @PointCut注解 切入点表达式的抽取 (用于标识切入点方法(公共的切入点表达式))
    • 2.4 连接点(连接点对象)
      • 2.4.1 JoinPoint连接点对象:对于除环绕通知外的其他所有通知,获取连接点信息只能使用JoinPoint
      • 2.4.2 ProceedingJoinPoint连接点对象:对于环绕通知,获取连接点信息只能使用ProceedingJoinPoint类型
  • 3. AOP案例:操作日志(重要!!!)
    • 3.1 需求:将案例中增、删、改相关接口的操作日志记录到数据库表中
    • 3.2 分析
    • 3.3 步骤
    • 3.4 实现
      • 3.4.1 准备工作
      • 3.4.2 编码实现


前言


1. AOP基础

在AOP基础这个阶段,我们首先介绍一下什么是AOP,再通过一个快速入门程序,让大家快速体验AOP程序的开发。最后再介绍AOP当中所涉及到的一些核心的概念。

1.1 AOP概述: 什么是AOP?

什么是AOP?

  • AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。

那什么又是面向方法编程呢,为什么又需要面向方法编程呢?来我们举个例子做一个说明:

比如,我们这里有一个项目,项目中开发了很多的业务功能。
在这里插入图片描述
然而有一些业务功能执行效率比较低,执行耗时较长,我们需要针对于这些业务方法进行优化。 那首先第一步就需要定位出执行耗时比较长的业务方法,再针对于业务方法再来进行优化。

此时我们就需要统计当前这个项目当中每一个业务方法的执行耗时。那么统计每一个业务方法的执行耗时该怎么实现?

可能多数人首先想到的就是在每一个业务方法运行之前,记录这个方法运行的开始时间。在这个方法运行完毕之后,再来记录这个方法运行的结束时间。拿结束时间减去开始时间,不就是这个方法的执行耗时吗?

以上分析的实现方式是可以解决需求问题的。但是对于一个项目来讲,里面会包含很多的业务模块,每个业务模块又包含很多增删改查的方法,如果我们要在每一个模块下的业务方法中,添加记录开始时间、结束时间、计算执行耗时的代码,就会让程序员的工作变得非常繁琐。

在这里插入图片描述

而AOP面向方法编程,就可以做到在不改动这些原始方法的基础上,针对特定的方法进行功能的增强。

AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行增强(无侵入性: 解耦)

我们要想完成统计各个业务方法执行耗时的需求,我们只需要定义一个模板方法,将记录方法执行耗时这一部分公共的逻辑代码,定义在模板方法当中,在这个方法开始运行之前,来记录这个方法运行的开始时间,在方法结束运行的时候,再来记录方法运行的结束时间,中间就来运行原始的业务方法。

在这里插入图片描述

而中间运行的原始业务方法,可能是其中的一个业务方法,比如:我们只想通过 部门管理的 list 方法的执行耗时,那就只有这一个方法是原始业务方法。 而如果,我们是先想统计所有部门管理的业务方法执行耗时,那此时,所有的部门管理的业务方法都是 原始业务方法。 那面向这样的指定的一个或多个方法进行编程,我们就称之为 面向切面编程。

简单了解了一下,相信已经发现了,这个AOP面向切面编程和我们在JavaSE里面学的动态代理技术很像,没错,这个技术的底层就是用动态代理实现的。

那此时,当我们再调用部门管理的 list 业务方法时啊,并不会直接执行 list 方法的逻辑,而是会执行我们所定义的 模板方法 , 然后再模板方法中:

  • 记录方法运行开始时间
  • 运行原始的业务方法(那此时原始的业务方法,就是 list 方法)
  • 记录方法运行结束时间,计算方法执行耗时

在这里插入图片描述

不论,我们运行的是那个业务方法,最后其实运行的就是我们定义的模板方法,而在模板方法中,就完成了原始方法执行耗时的统计操作 。(那这样呢,我们就通过一个模板方法就完成了指定的一个或多个业务方法执行耗时的统计)

而大家会发现,这个流程,我们是不是似曾相识啊?

对了,就是和我们之前所学习的动态代理技术是非常类似的。 我们所说的模板方法,其实就是代理对象中所定义的方法,那代理对象中的方法以及根据对应的业务需要, 完成了对应的业务功能,当运行原始业务方法时,就会运行代理对象中的方法,从而实现统计业务方法执行耗时的操作。

其实,AOP面向切面编程和OOP面向对象编程一样,它们都仅仅是一种编程思想,而动态代理技术是这种思想最主流的实现方式。而Spring的AOP是Spring框架的高级技术,旨在管理bean对象的过程中底层使用动态代理机制,对特定的方法进行编程(功能增强)

AOP的优势:

  1. 减少重复代码
  2. 提高开发效率
  3. 维护方便

1.2 AOP快速入门

我们一般会建一个aop包来存放所有的模版方法:

在了解了什么是AOP后,我们下面通过一个快速入门程序,体验下AOP的开发,并掌握Spring中AOP的开发步骤。

需求:统计各个业务层方法执行耗时。

实现步骤:

  1. 导入依赖:在pom.xml中导入AOP的依赖
  2. 编写AOP程序:针对于特定方法根据业务需要进行编程

为演示方便,可以自建新项目或导入提供的springboot-aop-quickstart项目工程

pom.xml

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

AOP程序:TimeAspect

@Component
@Aspect //当前类为切面类
@Slf4j
public class TimeAspect {@Around("execution(* com.itheima.service.*.*(..))") public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {//记录方法执行开始时间long begin = System.currentTimeMillis();//执行原始方法Object result = pjp.proceed();//记录方法执行结束时间long end = System.currentTimeMillis();//计算方法执行耗时log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);return result;}
}

重新启动SpringBoot服务测试程序(先把过滤器和拦截器都关了):

  • 根据id查询员工
    在这里插入图片描述
    在这里插入图片描述

我们也可以下断点看看:
在这里插入图片描述

我们通过AOP入门程序完成了业务方法执行耗时的统计,那其实AOP的功能远不止于此,常见的应用场景如下:

  • 记录系统的操作日志
  • 权限控制
  • 事务管理:我们前面所讲解的Spring事务管理,底层其实也是通过AOP来实现的,只要添加@Transactional注解之后,AOP程序自动会在原始方法运行前先来开启事务,在原始方法运行完毕之后提交或回滚事务

这些都是AOP应用的典型场景。

通过入门程序,我们也应该感受到了AOP面向切面编程的一些优势:

  • 代码无侵入:没有修改原始的业务方法,就已经对原始的业务方法进行了功能的增强或者是功能的改变

  • 减少了重复代码

  • 提高开发效率

  • 维护方便

1.3 Spring AOP核心中的相关术语(面试)

这部分建议写学完所有最后再来看才会清晰,不然压根不知道在讲什么

通过SpringAOP的快速入门,感受了一下AOP面向切面编程的开发方式。下面我们再来学习AOP当中涉及到的一些相关术语。

  • (1) 切面(Aspect):简单理解为一个包含了通知(advice)和切点(poincut)的类
    其实就是定义了一个Java 类,里面包含了通知(advice)和切点(poincut)定义了在何处以及何时执行通知,将切面的一些东西模块化了,即定义横切关注点的模块,封装了不同模块共享的功能.
    执行后或抛出异常时运行。
  • (2) 通知(Advice): 切面中的实际逻辑,即在连接点上执行的操作。通知可以在方法执行前(就是切面类里面使用了通知注解的哪些方法,所以通知就是方法)
    • 前置通知(Before advice): 在目标方法执行前执行。
    • 后置通知(After returning advice):在目标方法成功执行后执行。
    • 后置异常通知(After throwing advice):在目标方法抛出异常后执行。
    • 后置最终通知(After (finally) advice):无论目标方法如何结束(正常返回或抛出异常),都会执行。
    • 环绕通知(Around advice):在目标方法执行前后都执行,并且可以控制目标方法的执行过程,环绕通知可以用作日志打印或者权限校验。
  • (3) 切点(Pointcut): 切点是一个表达式,用于定义在哪些连接点上执行通知,简单理解就是通过这个表达式可以找到想要织入的哪些方法。
  • (4) 连接点(Join point): 连接点是程序执行过程中可以应用切面的点,例如方法的调用、方去的执行、异常的抛出等,可以拿到切入方法名等诸多属性。
    其实就是JoinPoint和ProceedingJoinPoint这两个连接点对象,我们可以从这个连接点对象中获取到目标方法的各种信息,目标方法的返回值、方法名、参数列表等(所以我们也可以简单理解连接点就是可以被aop控制的哪些目标方法)
  • (5) 目标对象(Target Object): 被切面增强的对象,也就是原本的业务类
    就是目标方法所在的哪些类对象,就称为目标对象
  • (6) 代理(Proxy): Spring AOP 通过生成代理对象来增强目标对象的方法。代理对象包含目对象的原始方法和增强逻辑。
    Spring AOP底层是动态代理,当然会有代理对象
  • (7) 织入(Weaving): 将切面应用到目标对象上的过程。Spring AOP 是在运行时进行织入的
    把通知应用到目标对象上的过程就称为织入

2. AOP进阶

AOP的基础知识学习完之后,下面我们对AOP当中的各个细节进行详细的学习。主要分为4个部分:

  1. 通知类型
  2. 通知顺序
  3. 切入点表达式
  4. 连接点

我们先来学习第一部分通知类型。

2.1 通知类型

2.1.1 @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有)

2.1.2 @Before:前置通知,此注解标注的通知方法在目标方法前被执行(通知的代码只放在业务方法之前)

2.1.3 @AfterReturning : 后置(返回)通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行(通知的代码只放在业务方法之后)

2.1.4 @After :后置最终通知,此注解标注的通知方法无论目标方法如何结束(正常返回或抛出异常),都会执行。(通知代码在 finally 的代码块之中)

2.1.5 @AfterThrowing : 后置异常通知,此注解标注的通知方法在目标方法抛出异常后执行。(通知代码在捕获异常 catch(){}的代码块之中)

在入门程序当中,我们已经使用了一种功能最为强大的通知类型:Around环绕通知。

@Around("execution(* com.itheima.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {//记录方法执行开始时间long begin = System.currentTimeMillis();//执行原始方法Object result = pjp.proceed();//记录方法执行结束时间long end = System.currentTimeMillis();//计算方法执行耗时log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);return result;
}

只要我们在通知方法上加上了@Around注解,就代表当前通知是一个环绕通知。

Spring中AOP的通知类型:

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(通知的代码在业务方法之前和之后都有
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行(通知的代码只放在业务方法之前
  • @AfterReturning : 后置(返回)通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行(通知的代码只放在业务方法之后
  • @After :(后置)最终通知,此注解标注的通知方法无论目标方法如何结束(正常返回或抛出异常),都会执行。(通知代码在 finally 的代码块之中
  • @AfterThrowing : (后置)异常通知,此注解标注的通知方法在目标方法抛出异常后执行。(通知代码在捕获异常 catch(){}的代码块之中

下面我们通过代码演示,来加深对于不同通知类型的理解:

@Slf4j
@Component
@Aspect
public class MyAspect1 {//前置通知@Before("execution(* com.itheima.service.*.*(..))")public void before(JoinPoint joinPoint){log.info("前置通知中代码执行了 ...");}//环绕通知@Around("execution(* com.itheima.service.*.*(..))")public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {log.info("环绕通知中before代码执行了  ...");//调用目标对象的原始方法执行Object result = proceedingJoinPoint.proceed();//原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了log.info("环绕通知中after代码执行了 ...");return result;}//后置最终通知@After("execution(* com.itheima.service.*.*(..))")public void after(JoinPoint joinPoint){log.info("最终通知中代码执行了 ...");}// 后置通知(程序在正常执行的情况下,会执行的后置通知)@AfterReturning("execution(* com.itheima.service.*.*(..))")public void afterReturning(JoinPoint joinPoint){log.info("后置通知中代码执行了 ...");}//异常通知(程序在出现异常的情况下,执行的后置通知)@AfterThrowing("execution(* com.itheima.service.*.*(..))")public void afterThrowing(JoinPoint joinPoint){log.info("异常通知执行了 ...");}
}

重新启动SpringBoot服务,进行测试:

1. 没有异常情况下:

  • 使用postman测试查询所有部门数据

在这里插入图片描述

  • 查看idea中控制台日志输出
    在这里插入图片描述

程序没有发生异常的情况下,@AfterThrowing标识的异常通知方法不会执行。

2. 出现异常情况下:

修改DeptServiceImpl业务实现类中的代码: 添加异常

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {@Autowiredprivate DeptMapper deptMapper

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

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

相关文章

七星棋牌 6 端 200 子游戏全开源修复版源码(乐豆 + 防沉迷 + 比赛场 + 控制)

七星棋牌源码 是一款运营级的棋牌产品&#xff0c;覆盖 湖南、湖北、山西、江苏、贵州 等 6 大省区&#xff0c;支持 安卓、iOS 双端&#xff0c;并且 全开源。这个版本是 修复优化后的二开版本&#xff0c;新增了 乐豆系统、比赛场模式、防沉迷机制、AI 智能控制 等功能&#…

【人工智能】Deepseek 与 Kimi 联袂:重塑 PPT 创作,开启智能演示新纪元

我的个人主页 我的专栏&#xff1a;人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞&#x1f44d;收藏❤ 前言 在当今快节奏的工作与学习场景中&#xff0c;PPT 制作常常是一项耗时耗力的任务。从前期的资…

基于JAVA+Spring+mysql_快递管理系统源码+设计文档

文末获取源码数据库文档 感兴趣的可以先收藏&#xff0c;有毕设问题&#xff0c;项目以及论文撰写等问题都可以和博主沟通&#xff0c;尽最大努力帮助更多的人&#xff01; 摘 要 随着物流行业信息化的深入使得物流过程中货物的状态和变化透明化&#xff0c;现代信息化的接入使…

Python----数据分析(Numpy:安装,数组创建,切片和索引,数组的属性,数据类型,数组形状,数组的运算,基本函数)

一、 Numpy库简介 1.1、概念 NumPy(Numerical Python)是一个开源的Python科学计算库&#xff0c;旨在为Python提供 高性能的多维数组对象和一系列工具。NumPy数组是Python数据分析的基础&#xff0c;许多 其他的数据处理库&#xff08;如Pandas、SciPy&#xff09;都依赖于Num…

【SQL】MySQL中的字符串处理函数:concat 函数拼接字符串,COALESCE函数处理NULL字符串

MySQL中的字符串处理函数&#xff1a;concat 函数 一、concat &#xff08;&#xff09;函数 1.1、基本语法1.2、示例1.3、特殊用途 二、COALESCE&#xff08;&#xff09;函数 2.1、基本语法2.2、示例2.3、用途 三、进阶练习 3.1 条件和 SQL 语句3.2、解释 一、concat &…

JAVA面试常见题_基础部分_Dubbo面试题(上)

Dubbo 支持哪些协议&#xff0c;每种协议的应用场景&#xff0c;优缺点&#xff1f; • dubbo&#xff1a; 单一长连接和 NIO 异步通讯&#xff0c;适合大并发小数据量的服务调用&#xff0c;以及消费者远大于提供者。传输协议 TCP&#xff0c;异步&#xff0c;Hessian 序列化…

StableDiffusion打包 项目迁移 项目分发 1

文章目录 SD项目迁移前置知识webui-user.batwebui.batlaunch_utils.py 下一篇开始实践 SD项目迁移 显卡驱动更新&#xff1a;https://www.nvidia.cn/geforce/drivers/ 下载安装三个程序&#xff1a; python3.10.6: https://www.python.org/downloads/release/python-3106/gi…

vscode使用豆包MARSCode----集成doubao1.5 DeepSeekR1 DeepseekV3模型的ai编程插件

引入扩展 打开VSCode扩展窗口&#xff0c;在搜索窗口搜索MarsCode&#xff0c;找到MarsCode 插件单击「install」&#xff0c;完成安装&#xff0c;登录即可使用MarsCode 编程助手。 主要功能 主要快捷键 / explain 解释项目代码&#xff0c;AI 返回的内容有结构分类&#…

uni小程序wx.switchTab有时候跳转错误tab问题,解决办法

在一个子页面里面使用uni.switchTab或者wx.switchTab跳转到tab菜单的时候&#xff0c;先发送了一个请求&#xff0c;然后执行跳转到tab菜单&#xff0c;但是这个时候&#xff0c;出错了........也是非常的奇怪&#xff0c;不加请求就没问题......但是业务逻辑就是要先执行某个请…

【Kimi】自动生成PPT-并支持下载和在线编辑--全部免费

【Kimi】免费生成PPT并免费下载 用了好几个大模型&#xff0c;有些能生成PPT内容&#xff1b; 有些能生成PPT&#xff0c;但下载需要付费&#xff1b; 目前只有Kimi生成的PPT&#xff0c;能选择模板、能在线编辑、能下载&#xff0c;关键全部免费&#xff01; 一、用kimi生成PP…

编写一个程序,计算并输出1到100的和(Python版)

编写一个程序&#xff0c;计算并输出1到100的和 以下是两种计算1到100之和的方法&#xff1a; 方法一&#xff1a;循环累加法&#xff08;适合编程练习&#xff09; total 0 for num in range(1, 101):total num print("1到100的和为:", total)原理&#xff1a;通…

向量数据库milvus部署

官方文档 Milvus vector database documentationRun Milvus in Docker (Linux) | Milvus DocumentationMilvus vector database documentation 按部署比较简单&#xff0c;这里说一下遇到的问题 一&#xff1a;Docker Compose 方式部署 1、镜像无法拉取,(docker.io被禁) …

【密码学实战】Java 实现 SM2 国密算法(签名带id、验签及 C1C3C2 加密解密)

前言 SM2是中国国家密码管理局发布的椭圆曲线公钥密码算法标准&#xff08;GB/T 32918&#xff09;&#xff0c;属于国密算法体系。与RSA和ECDSA相比&#xff0c;SM2在相同安全强度下密钥更短、计算效率更高。本文将介绍如何在Java中实现SM2的密钥生成、数字签名、验签、加密及…

网络原理---TCP/IP

活动发起人小虚竹 想对你说&#xff1a; 这是一个以写作博客为目的的创作活动&#xff0c;旨在鼓励大学生博主们挖掘自己的创作潜能&#xff0c;展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴&#xff0c;那么&#xff0c;快来参加吧&#xff01…

eMMC安全简介

1. 引言 术语“信息安全”涵盖多种不同的设计特性。一般而言&#xff0c; 信息安全是指通过实践防止信息遭受未经授权的访问、使用、披露、中断、篡改、检查、记录或销毁。 信息安全的三大核心目标为 机密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integr…

Python 数据结构 2.时间复杂度和空间复杂度

Life is a journey —— 25.2.28 一、引例&#xff1a;穷举法 1.单层循环 所谓穷举法&#xff0c;就是我们通常所说的枚举&#xff0c;就是把所有情况都遍历了的意思。 例&#xff1a;给定n&#xff08;n ≤ 1000&#xff09;个元素ai&#xff0c;求其中奇数有多少个 判断一…

FFmpeg-chapter3-读取视频流(原理篇)

ffmpeg网站&#xff1a;About FFmpeg 1 库介绍 &#xff08;1&#xff09;libavutil是一个包含简化编程函数的库&#xff0c;包括随机数生成器、数据结构、数学例程、核心多媒体实用程序等等。 &#xff08;2&#xff09;libavcodec是一个包含音频/视频编解码器的解码器和编…

面试(进阶) —虚拟列表在什么场景使用,如何实现?

面试(进阶) —虚拟列表在什么场景使用&#xff0c;如何实现&#xff1f; 在前端开发中&#xff0c;当需要渲染大量数据时&#xff0c;传统的渲染方式往往会遇到性能瓶颈。一次性将大量数据渲染到DOM中&#xff0c;不仅会导致页面加载缓慢&#xff0c;还可能占用大量内存&#x…

Linux Mem -- 关于AArch64 MTE功能的疑问

目录 1.虚拟地址和物理地址映射完成后&#xff0c;才可以设置虚拟地址对应的memory tag &#xff1f; 2.各种memory allocator中的address tag从哪来&#xff0c;怎么产生&#xff1f; 2.1 vmalloc allocator 2.2 slub分配器 2.3 用户可以指定IRG指令产生的address tag 3.kasan…

python-leetcode-颜色分类

75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; class Solution:def sortColors(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""low, mid, high 0, 0, len(nums) - 1while mid < h…