02 面向切面编程(AOP)核心概念:Aspect

02 面向切面编程(AOP)核心概念:Aspect

  • 一 定义
  • 二 构成要素
    • 1. Advice(通知)
    • 2. Pointcut(切点)
    • 3. Join Point(连接点)
  • 三 织入(Weaving)
  • 四 样例代码
    • 1. 引入依赖
    • 2. 新建Controller
    • 3. 新建切面类(LoggingAspect)
  • 五 测试截图

在这里插入图片描述

一 定义

Aspect 在编程中,尤其是 面向切面编程Aspect Oriented Programming,简称 AOP )中,是一个核心概念。它代表了一个跨越多个类和方法的关注点或功能的集合。这些关注点或功能通常与业务逻辑不直接相关,而是与系统的横切关注点有关,如日志记录、事务管理、权限验证等。通过使用 Aspect ,开发者可以将这些横切关注点从业务逻辑中分离出来,从而实现关注点与业务逻辑的解耦,提高代码的可维护性和重用性。

二 构成要素

一个完整的 Aspect 通常包含以下几个关键组成部分:

1. Advice(通知)

AdviceAspect 中具体实施横切关注点行为的部分,即在特定的程序执行点(Join Point)插入的额外操作。根据执行时机的不同,Advice 可分为以下几种类型:

类型简述
Before advice前置通知;在目标方法执行之前执行。
After returning advice返回后通知;在目标方法正常返回后执行。
After throwing advice抛出异常后通知;在目标方法抛出异常后执行。
After (finally) advice最终通知/最终回归通知;无论目标方法是否正常结束或抛出异常,都会在方法执行完毕后执行。
Around advice环绕通知;包围目标方法的执行,可以决定何时调用原方法、何时执行前置或后置动作,甚至完全阻止原方法的执行。

2. Pointcut(切点)

Pointcut 是一种表达式或模式,用于指定一组相关的Join Points(程序执行过程中的特定位置,如方法调用、属性访问等),即定义了 Advice 应该在哪些特定的连接点上应用。切点表达式可以基于方法签名、类名、注解、包结构等多种条件进行匹配。

3. Join Point(连接点)

Join Point 是程序执行过程中一个明确的点,通常是方法调用、异常抛出、字段访问等事件的发生时刻。它是 Advice 可以介入并添加相应行为的地方。 Join Points 构成了程序执行流程中的所有可能干预点集合。

三 织入(Weaving)

Weaving 是将 Aspect 与应用程序的其他代码(包括主业务逻辑)进行融合以生成最终可执行程序的过程。Weaving 可以在不同的阶段进行:

阶段简述
编译时(Compile-time)通过特殊的编译器或插件,将 Aspect 转换为普通 Java 字节码。
类加载时(Load-time)使用特殊的类加载器,在加载类文件时动态地将 Aspect 逻辑合并到目标类中。
运行时(Runtime)通过代理机制(如 JDK 动态代理或 CGLIB 代理)在程序运行过程中动态地将 Aspect 逻辑织入目标对象。

四 样例代码

一个常见的使用 Aspect 的场景是日志记录。假设我们有一个业务方法,我们希望在方法执行前后记录日志。通过使用 Aspect ,我们可以创建一个日志记录的 Aspect ,然后在业务方法上应用这个 Aspect ,而无需修改业务方法的代码。

1. 引入依赖

<!-- Spring AOP: 提供AOP相关的注解。如:@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>[版本号]</version>
</dependency>

2. 新建Controller

package com.demo.springboot3.controller;import com.demo.springboot3.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;/*** @Description: // 用户信息:Controller* @Author: M.* @Date: 2024-04-25 20:11*/
@RestController
public class UserController {private Logger logger = LoggerFactory.getLogger(UserController.class);@PostMapping("/query")public String queryUser(@RequestBody User user) {logger.info("执行了业务方法!");return "success";}
}

3. 新建切面类(LoggingAspect)

package com.demo.springboot3.aspect;import com.demo.springboot3.controller.UserController;
import com.demo.springboot3.entity.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;/*** @Description: // 用户:切面* @Author: M.* @Date: 2024-04-28 10:11*/
@Aspect
@Component
public class LoggingAspect {private Logger logger = LoggerFactory.getLogger(UserController.class);@Pointcut("execution(* com.demo.springboot3.controller.UserController.queryUser(..))")public void pointCut() {}@Before("pointCut()")public void before(JoinPoint joinPoint) {logger.info("Entering method: " + joinPoint.getSignature());Object[] args = joinPoint.getArgs();User user = (User) args[0];logger.info("Parameter: " + user);// 此处执行一些记录日志,或者执行其他业务逻辑}@AfterReturning(pointcut = "pointCut()", returning = "result")public Object afterReturning(JoinPoint joinPoint, Object result) {logger.info("Entering method: " + joinPoint.getSignature() + " executed successfully and returned: " + result);// 此项执行一些记录日志,或者执行其他业务逻辑。如果业务逻辑无返回值,则不需要return,返回值类型修改为Voidreturn result;}@AfterThrowing(pointcut = "pointCut()", throwing = "e")public void afterThrowing(JoinPoint joinPoint, Exception e) {logger.info("Entering method: " + joinPoint.getSignature() + "; throw an exception: " + e.getMessage());// 此处执行一些记录异常信息到日志系统,或者执行其他异常处理逻辑}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();// 在目标方法执行前打印日志logger.info("Entering method: " + joinPoint.getSignature());// 继续执行目标方法,并获取其返回值Object result = joinPoint.proceed();long endTime = System.currentTimeMillis();// 在目标方法执行后打印日志logger.info("Entering method: " + joinPoint.getSignature() + " - took " + (endTime - startTime) + "ms");return result;}@After("pointCut()")public void after(JoinPoint joinPoint) {logger.info("Entering method: " + joinPoint.getSignature() + " has finished execution.");// 此处执行一些清理工作,比如释放资源、记录方法执行结束日志等}
}

上述代码为案例代码,根据实际情况,自行搭配使用。

注解简述
@Aspect注解标识 LoggingAspect 类为一个切面类。
@Pointcut注解用于定义一个切入点表达式,以便识别目标方法。
execution(* com.... 第一个 * 目标方法的返回值。
com.demo.springboot3.controller.UserController.queryUser是指定目标方法。
execution(* com.....queryUser(..)).. 是目标方法的参数类型,可以用..代替。
execution(* com.demo.....UserController.*(..))该路径下的所有方法。
@Before注解标识 before()方法为一个前置通知。
@AfterReturning注解用于在目标方法成功返回后执行特定的操作。通常用于目标方法执行完毕后执行一些后续逻辑,比如记录日志、进行数据操作或者发送通知等。
@AfterThrowing注解用于定义一个异常通知,它会在目标方法抛出异常后执行。常用于处理或记录方法执行过程中出现的异常。
@Around此注解用于定义一个环绕通知,它会在目标方法执行前后都执行,并且可以控制目标方法的执行。环绕通知通常用于在方法执行前后添加额外的逻辑,并可以决定是否调用目标方法。
@After注解用于在目标方法执行完毕后(无论目标方法是否抛出异常),都会执行指定的通知方法。这种通知类型通常用于执行一些清理工作,比如释放资源、记录方法执行结束日志等。
JoinPointjoinPoint.getSignature():获取通知的签名
joinPoint.getSignature().getDeclaringTypeName():获取代理类的名字
joinPoint.getSignature().getName():获取代理方法的名字
joinPoint.getArgs():获取目标方法的参数列表信息(返回值是由参数构成的数组)。
joinPoint.getThis(): AOP代理类的信息
joinPoint.getTarget(): 代理的目标对象

五 测试截图

⚠️⚠️⚠️注意:
上述通知注解可以共存,关键在于如何合理设计切面逻辑,避免相互之间的干扰,并确保正确的执行流程。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


本文隶属于 个人专栏00 个人小笔记📋📋📋
到这里 02 面向切面编程(AOP)核心概念:Aspect 就结束了!!!🎉🎉🎉
欢迎小伙伴们学习和指正!!!😊😊😊
祝大家学习和工作一切顺利!!!😎😎😎

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

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

相关文章

为什么3d模型都没有细分---模大狮模型网

在3D设计领域&#xff0c;3D模型是设计师和艺术家们创作的重要作品之一&#xff0c;它们在游戏开发、影视制作、工程建设等领域中扮演着重要角色。然而&#xff0c;尽管有着如此广泛的应用&#xff0c;但在互联网上搜索3D模型时&#xff0c;常常会发现缺乏足够的细分分类。为什…

AtCoder Beginner Contest 351 A~F

A.The bottom of the ninth(思维) 题意 有两只队伍正在进行棒球游戏&#xff0c;每只队伍都有 9 9 9个回合&#xff0c;先手已经结束了所有的回合&#xff0c;并获得了 A 1 , A 2 , … , A 9 A_1, A_2, \ldots, A_9 A1​,A2​,…,A9​分数&#xff0c;而后手只进行了8轮&…

华为鸿蒙应用--封装通用标题栏:CommonTitleBar(鸿蒙工具)-ArkTs

0、效果图 自定义通用标题栏 支持左、中、右常规标题栏设置&#xff1b; 支持自定义视图&#xff1b; 支持搜索功能 一、CommTitleBar代码 import router from ohos.router; import { Constants } from ../../constants/Constants; import { StyleConstants } from ../../…

数据结构 - 顺序表

一. 线性表的概念 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的…

Github进行fork后如何与原仓库同步[解决git clone 太慢的问题]

前言 fork了一个仓库以后怎么同步源仓库的代码&#xff1f; 先说一下git clone太慢的问题&#xff0c;可以通过代理拉取代码&#xff0c;具体请看&#xff1a; https://gitclone.com/ 步骤 1、执行命令 git remote -v 查看你的远程仓库的路径。 以一个实际例子说明&#x…

docker容器通俗理解

前言 如果大家没使用过Docker,就在电脑上下载一个VMware Workstation Pro&#xff0c;创建一个虚拟机安装一个windows操作一下感受一下,为什么我的电脑上还以再安装一台windows主机&#xff1f;其实你可以理解为Docker就是Linux系统的一个虚拟机软件。 我的Windows也可以安装…

【高校科研前沿】东北地理所孙敬轩博士为一作在《中国科学:地球科学(中英文版)》发文:气候变化下东北地区农业绿水安全风险评估

目录 01 文章简介 02 研究内容 03 文章引用 04 期刊简介 01 文章简介 论文名称&#xff1a;Risk assessment of agricultural green water security in Northeast China under climate change&#xff08;气候变化下东北地区农业绿水安全风险评估&#xff09; 第一作者及…

猫咪冻干究竟怎么选不踩雷?这几款生骨肉冻干一定适合你家喵

315中国之声的报道揭示了河北省邢台市南和区某宠粮代工厂的“行业秘密”&#xff0c;这无疑给广大宠物主人敲响了警钟。配料表上标注的鸡肉含量高达52%&#xff0c;新鲜鸡小胸占20%&#xff0c;然而所谓的鲜鸡肉实际上却是鸡肉粉。我们养宠物本是为了心灵上的慰藉&#xff0c;但…

栈和队列总结

文章目录 前言一、栈和队列的实现1.栈的具体实现2.循环顺序队列的具体实现 二、栈和队列总结总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#xff0c;便于日后复习&#xff08;这种事情不要啊&#xff09;。所用教材为《数据结构 C语言版…

揭秘Linux文件系统

前言 在上一篇文件描述符详解中谈论的都是打开的文件&#xff0c;但是在我们的系统中不仅有打开的文件还有许多未打开的文件&#xff0c;那么这些未打开的文件又该如何理解呢?阅读完本篇文章相信你会得到答案。 如果觉得文章内容对你有所帮助的话&#xff0c;可以给博主一键三…

新装电脑Flutter环境部署坑汇总(持续更新)

1.本地安装&#xff0c;安装fvm的坑 本人电脑使用windows &#xff0c;安装fvm则一般使用choco安装&#xff0c;那么首先需要安装choco,打开powershell/或者cmd运行以下命令&#xff1a; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager…

图像置乱加密-Arnold加密算法

置乱加密是另一种较常用的加密方法&#xff0c;现也被许多文献选用&#xff0c;置乱加密可以是以像素为单位进行全局置乱&#xff0c;该方式打乱了图像像素值的位置&#xff0c;使其图像内容失去相关性&#xff0c;达到保护的目的。也可以是以块为单位进行置乱&#xff0c;该方…

Kafka报错ERROR Exiting Kafka due to fatal exception during startup

报错&#xff1a; ERROR Exiting Kafka due to fatal exception during startup. (kafka.Kafka$) kafka.common.InconsistentClusterIdException: The Cluster ID FSzSO50oTLCRhRnRylihcg doesnt match stored clusterId Some(0oSLohwtQZWbIi73YUMs8g) in meta.properties. Th…

某宝因SSL证书过期无法正常访问,证书过期问题频发企业如何破局?

近日&#xff0c;有网友发现&#xff0c;某宝网站无法正常访问&#xff0c;出现“此连接非私人连接”提示&#xff0c;而导致此类提示的罪魁祸首是因为SSL证书过期&#xff01;其实&#xff0c;近年来&#xff0c;因SSL证书过期导致的网站无法正常访问的事件频频发生&#xff0…

vue2—— mixin 超级详细!!!

mixin Mixin是面向对象程序设计语言中的类&#xff0c;提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类 Mixin类通常作为功能模块使用&#xff0c;在需要该功能时“混入”&#xff0c;有利于代码复用又避免了多继承的复杂 vue中的mixin 先来看一下官方定义 mi…

YOLO-yolov5构建数据集

1.收集数据集 创建一个dataset文件夹用来存放图片数据集。 我这里使用的图片数据集&#xff0c;是对一段视频进行抽帧得到的200张狗狗图片。 在dataset文件夹下新建images和labels文件夹&#xff0c;并将200张狗狗图片放入images中。 2.标注数据集 2.1安装标注工具labelimg…

Jenkins邮件发送失败问题解决

如下提示为 Extended E-mail Notification开启Debug模式下显示的错误信息&#xff0c; (Debug模式设置方法&#xff1a;Dashboard-> manage Jenkins->configure System)DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEB…

OpenCV——Bernsen局部阈值二值化方法

目录 一、Bernsen算法1、算法概述2、参考文献二、代码实现三、结果展示Bernsen局部阈值二值化方法由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、Bernsen算法 1、算法概述 Bernsen 算法是另一种流行的局部阈值二值化方…

网络相关知识总结

1、网口设置 网口设置IP&#xff0c;即操作/etc/sysconfig/network-scripts路径下的ifcfg-xx文件 主要参数详解&#xff1a; DEVICE:网口名 ONBOOT&#xff1a;表示启动系统时是否激活网卡&#xff0c;yes为激活&#xff0c;no不激活 HWADDR:mac值 DEFROUTE://默认路由设置…

Docker容器:docker基础

目录 一.docker前言 云计算服务模式 关于 docker 产品 虚拟化产品有哪些&#xff1f; ① 寄居架构 ② 源生架构 虚拟化技术概述 主流虚拟化产品对比 1. VMware系列 2. KVM/OpenStack 3. Xen 4. 其他半/全虚拟化产品 二. docker 的相关知识 1. docker 的概念 doc…