【Spring AOP】_使用注解编写AOP程序

目录

1. 以增加方法执行时间为例使用AOP

1.1 引入AOP依赖

1.2 编写AOP程序

2. AOP的重要概念

3. AOP通知类型与通知方法标注

3.1 在通知方法前使用对应注解

3.2 使用@Pointcut注解提取公共切点表达式

3.3 跨类使用切点

3.4 切面类排序


1. 以增加方法执行时间为例使用AOP

1.1 引入AOP依赖

在pom.xml中增加关于AOP的配置:

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

1.2 编写AOP程序

以图书管理系统为例,为每个方法增加耗时计算与日志打印。

创建aspect包,在其下创建TimeAspect类:

package com.example.bookmanagementsystem.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Aspect
@Slf4j
@Component
public class TimeAspect {@Around("execution(* com.example.bookmanagementsystem.controller.*.*(..))")public Object timeCost(ProceedingJoinPoint joinPoint) throws Throwable {long start=System.currentTimeMillis();// 执行目标方法Object result=joinPoint.proceed();long end=System.currentTimeMillis();log.info(joinPoint+"消耗时间:"+(end-start)+"ms");return result;}
}

关于注解:

1、@Aspect:表示该类是一个切面类;

2、@Around:用于指明切面类的作用域与作用方式(在哪个环节,对哪些方法);

关于切面类成员方法:

1、timeCost方法的参数是一个ProceedingJoinPoint类型的对象,表示目标方法;

2、代码被分为三大部分:

2. AOP的重要概念

1、切点:一组通过表达式描述的规则;

2、连接点:切面作用/描述的方法,即被AOP控制的目标方法;

3、通知:具体要做处理的逻辑;

4、切面:切点+通知即切面,一个类可以有多个切面;

以上述切面类为例:

3. AOP通知类型与通知方法标注

1、@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行(最常用)

2、@Before:前置通知,此注解标注的通知方法在目标方法前被执行;

3、@After

后置通知,此注解标注的通知方法在目标方法后被执行,无论是否发生异常都会执行

4、@AfterReturning

返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

5、@AfterThrowing:异常后通知,此注解标注的通知方法在异常后被执行

3.1 在通知方法前使用对应注解

现在controller包下创建一个HelloController类,编写方法作为目标方法:

由于@AfterReturning与@AfterThrowing标注的方法在异常发生与否时返回不同,故编写两个方法使其满足一个正常运行,一个运行时报异常:

package com.zhouyou.demos.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@RequestMapping("/test1")public String test1(){return "hello";}@RequestMapping("/test2")public int test2(){return 10/0;}
}

在aspect包下创建TestAspect类,用于编写通知方法:

package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Slf4j
@Component
public class AspectDemo {@Around("execution(* com.zhouyou.demos.controller.*.*(..))")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info("AspectDemo around 前");Object result=joinPoint.proceed();log.info("AspectDemo around 后");return result;}@Before("execution(* com.zhouyou.demos.controller.*.*(..))")public void doBefore(){log.info("AspectDemo before");}@After("execution(* com.zhouyou.demos.controller.*.*(..))")public void doAfter(){log.info("AspectDemo after");}@AfterReturning("execution(* com.zhouyou.demos.controller.*.*(..))")public void doAfterReturning(){log.info("AspectDemo afterReturning");}@AfterThrowing("execution(* com.zhouyou.demos.controller.*.*(..))")public void doAfterThrowing(){log.info("AspectDemo afterThrowing");}
}

启动项目,依次根据路由映射访问test1方法和test2方法,可查看日志观察通知方法执行顺序:

3.2 使用@Pointcut注解提取公共切点表达式

上述使用方法中,在使用对应注解标注通知方法时,需要重复编写公共切点表达式,这很不方便;

可使用@Pointcut提取公共切点表达式,在后续使用公共切点表达式时则直接使用@Pointcut标注的方法名即可;

修改3.1中的代码

package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Slf4j
@Component
public class AspectDemo {@Pointcut("execution(* com.zhouyou.demos.controller.*.*(..))")private void pc(){}@Around("pc()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info("AspectDemo around 前");Object result=joinPoint.proceed();log.info("AspectDemo around 后");return result;}@Before("pc()")public void doBefore(){log.info("AspectDemo before");}@After("pc()")public void doAfter(){log.info("AspectDemo after");}@AfterReturning("pc()")public void doAfterReturning(){log.info("AspectDemo afterReturning");}@AfterThrowing("pc()")public void doAfterThrowing(){log.info("AspectDemo afterThrowing");}
}

3.3 跨类使用切点

现在aspect包中再创建一个切面类aspectDemo2,以@Before为例使用aspectDemo的切点。

package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Slf4j
@Component
public class AspectDemo2 {@Before("com.zhouyou.demos.aspect.AspectDemo.pc()")public void doBefore(){log.info("AspectDemo2 doBefore");}
}

启动项目,根据方法路由映射即可在日志处观察到通知方法的具体执行顺序情况;

使用方法注意事项:

(1)在跨类使用公共切点时,需要使用全限定类名;

(2)在当前类中,若在其类中实现的切点需要在其他类中使用,则切点必须以public修饰。

使用private修饰的切点只能在当前类中使用;

3.4 切面类排序

现aspect包下由AspectDemo、AspectDemo1、AspectDemo2三个切面类,并在每个切面类中实现@Before通知和@After通知。

创建目标方法并指定路由映射,并进行访问,查看日志输出:

在采取默认排序的情况下,默认采取按照切面类的类名字母排序:

对于@Before通知,排名越靠前的先执行;

对于@After通知,排名越靠后的先执行;

但这并不便于管理,Spring提供了@Order注解,用于给切面类设置优先级

对于@Before通知,@Order中的数字越小越先执行;

对于@After通知,@Order中的数字越大越先执行;

现对AspectDemo切面类使用Order(3)、AspectDemo1切面类使用Order(2)、AspectDemo2切面类使用Order(1),启动程序查看日志输出:

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

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

相关文章

C# iText 抽取PDF页特定区域文本内容

开发中需要提取PDF文件某页某区域内的特定文本内容&#xff0c;对于文字转换而成的PDF文件&#xff0c;可以使用iText库&#xff0c;通过Rectangle划定PDF页中特定区域提取文字&#xff0c;思路是将这个Rectangle框定区域放到TextRegionEventFilter过滤器中&#xff0c;代码如下…

Java 关键字 volatile

volatile 是 Java 中的一个关键字&#xff0c;用于修饰变量&#xff0c;确保多线程环境下的可见性和有序性。它主要用于解决以下两个问题&#xff1a; 可见性问题&#xff1a;一个线程对 volatile 变量的修改对其他线程立即可见。有序性问题&#xff1a;禁止指令重排序&#x…

python网络爬虫开发实战之基本库使用

目录 第二章 基本库的使用 2.1 urllib的使用 1 发送请求 2 处理异常 3 解析链接 4 分析Robots协议 2.2 requests的使用 1 准备工作 2 实例引入 3 GET请求 4 POST请求 5 响应 6 高级用法 2.3 正则表达式 1 实例引入 2 match 3 search 4 findall 5 sub 6 com…

Linux内存分页:原理、优势与实践

一、分页机制核心原理 1.1 分页技术原理 核心思想: 将虚拟地址空间和物理内存划分为固定大小的页(Page),通过页表(Page Table)建立虚拟页到物理页框(Page Frame)的映射。例如,x86_64架构的4级页表结构: 虚拟地址: [63-48] | [47-39] PGD | [38-30] PUD | [29-21]…

文件上传漏洞与phpcms漏洞安全分析

目录 1. 文件上传漏洞简介 2. 文件上传漏洞的危害 3. 文件上传漏洞的触发条件 1. 文件必须能被服务器解析执行 2. 上传目录必须支持代码执行 3. 需要能访问上传的文件 4. 例外情况&#xff1a;非脚本文件也可能被执行 4. 常见的攻击手法 4.1 直接上传恶意文件 4.2 文件…

模块和端口

1、模块 模块内部的5个组成是&#xff1a;变量声明 数据流语句 低层模块实例 函数和任务 行为语句 SR锁存器 timescale 1ns / 1psmodule SR_latch(input wire Sbar ,input wire Rbar ,output wire Q ,output wire Qbar);nand…

爬虫(持续更新ing)

爬虫&#xff08;持续更新ing&#xff09; # 网络请求 # url统一资源定位符&#xff08;如&#xff1a;https://www.baidu.com&#xff09; # 请求过程&#xff1a;客户端的web浏览器向服务器发起请求 # 请求又分为四部分&#xff1a;请求网址&#xff0c;请求方法&#xff08…

2025.3.2机器学习笔记:PINN文献阅读

2025.3.2周报 一、文献阅读题目信息摘要Abstract创新点网络架构实验结论不足以及展望 一、文献阅读 题目信息 题目&#xff1a; Physics-Informed Neural Networks of the Saint-Venant Equations for Downscaling a Large-Scale River Model期刊&#xff1a; Water Resource…

使用IDEA如何隐藏文件或文件夹

选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹

前端基础之脚手架

脚手架结构 目录结构 这里的package.json&#xff0c;存放着我们去执行npm run serve 或是npm run build的脚本文件 package-lock.json中存放着我们使用的外部包的版本类型&#xff0c;相当于maven src下的main.js是整个项目的入口文件 src下的components用于存放组件&#xff…

MacBook上API调⽤⼯具推荐

在当今的软件开发中&#xff0c;API调用工具已经成为了开发者不可或缺的助手。无论是前端、后端还是全栈开发&#xff0c;API的调试、测试和管理都是日常工作中的重要环节。想象一下&#xff0c;如果没有这些工具&#xff0c;开发者可能需要手动编写复杂的CURL命令&#xff0c;…

pgsql行列转换

目录 一、造测试数据 二、行转列 1.函数定义 2.语法 3.示例 三、列转行 1.函数定义 2.语法 3.示例 一、造测试数据 create table test ( id int, json1 varchar, json2 varchar );insert into test values(1,111,{111}); insert into test values(2,111,222,{111,22…

NVIDIA(英伟达) GPU 芯片架构发展史

GPU 性能的关键参数 CUDA 核心数量&#xff08;个&#xff09;&#xff1a;决定了 GPU 并行处理能力&#xff0c;在 AI 等并行计算类业务下&#xff0c;CUDA 核心越多性能越好。 显存容量&#xff08;GB&#xff09;&#xff1a;决定了 GPU 加载数据量的大小&#xff0c;在 AI…

《Python实战进阶》No 10:基于Flask案例的Web 安全性:防止 SQL 注入、XSS 和 CSRF 攻击

第10集&#xff1a;Web 安全性&#xff1a;防止 SQL 注入、XSS 和 CSRF 攻击 在现代 Web 开发中&#xff0c;安全性是至关重要的。无论是用户数据的保护&#xff0c;还是系统稳定性的维护&#xff0c;开发者都需要对常见的 Web 安全威胁有深刻的理解&#xff0c;并采取有效的防…

【大数据分析 | 深度学习】在Hadoop上实现分布式深度学习

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘&#xff0c;以提取有价值的信息和洞察。它结合了大数据技术、人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&a…

盛铂科技SCP4000射频微波功率计与SPP5000系列脉冲峰值 USB功率计 区别

在射频&#xff08;RF&#xff09;和微波测试领域&#xff0c;快速、精准的功率测量是确保通信系统、雷达、卫星设备等高性能运行的核心需求。无论是连续波&#xff08;CW&#xff09;信号的稳定性测试&#xff0c;还是脉冲信号的瞬态功率分析&#xff0c;工程师都需要轻量化、…

自学微信小程序的第十三天

DAY13 1、使用map组件在页面中创建地图后&#xff0c;若想在JS文件中对地图进行控制&#xff0c;需要通过地图API来完成。先通过wx.createMapContext()方法创建MapContext&#xff08;Map上下文&#xff09;实例&#xff0c;然后通过该实例的相关方法来操作map组件。 const m…

深入解析 C# 中的泛型:概念、用法与最佳实践

C# 中的 泛型&#xff08;Generics&#xff09; 是一种强大的编程特性&#xff0c;允许开发者在不预先指定具体数据类型的情况下编写代码。通过泛型&#xff0c;C# 能够让我们编写更灵活、可重用、类型安全且性能优良的代码。泛型广泛应用于类、方法、接口、委托、集合等多个方…

H5DS编辑器是如何让企业快速构建动态页面

H5DS编辑器核心亮点&#xff1a; 1.拖拽式操作&#xff0c;小白友好&#xff1a;无需设计与代码基础&#xff01;通过简单拖拽元素、调整文字和动画&#xff0c;即可生成交互式H5页面。内置海量模板和素材库&#xff0c;支持自定义设计风格&#xff0c;轻松适配企业品牌需求。…

Unity ECS与MonoBehaviour混合架构开发实践指南

一、混合架构设计背景 1. 技术定位差异 ECS&#xff08;Entity Component System&#xff09;&#xff1a;面向数据设计&#xff08;DOD&#xff09;&#xff0c;适用于大规模实体计算&#xff08;如10万单位战斗&#xff09; MonoBehaviour&#xff1a;面向对象设计&#xf…