Spring-AOP
目录
一:什么是AOP
二:AOP快速入门
2.1导入AOP坐标
2.2定义dao接口和实现类
2.3定义通知类
2.4在配置类中进行Spring注解包扫描和开启AOP功能
2.5定义测试类测试结果
三:AOP工作流程
四:AOP的切入点表达式
4.1语法格式
4.2通配符
五:AOP通知类型
5.1前置通知
5.2后置通知
5.3最终通知
5.4异常通知
5.5环绕通知
六:总结
一:什么是AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
总的来说,AOP就是一编程规范,目的是在不改变方法源代码的基础上对方法进行功能增强。
二:AOP快速入门
2.1导入AOP坐标
在pom.xml中导入aop坐标
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.31</version></dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version></dependency>
2.2定义dao接口和实现类

BookDao接口中:
package com.lcyy.dao;public interface BookDao {void read();
}
实现类:注意要在BookDaoImpl方法上加入注解@Repository表示为交给Spring的一个组件
import com.lcyy.dao.BookDao;
import org.springframework.stereotype.Repository;@Repository
public class BookDaoImpl implements BookDao {@Overridepublic void read() {System.out.println("BookDao AOP 实现");}
}
2.3定义通知类

建立一个aop的包,在包下建立一个MyAdvice的通知类
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component//放在普通类上,交给ioc容器管理
@Aspect//定义这个类为切面类
public class MyAdvice {//定义连接点@Pointcut("execution(void com.lcyy.dao.BookDao.read())")private void pc(){}//定义通知@Before("pc()")public void testAdvice(){System.out.println("执行前的时间毫秒值:");System.out.println(System.currentTimeMillis());}
}

注意:
1.在MyAdvice类上要加入注解:@Aspect表示定义为一个切面类,@Component表示交给ioc容器管理。
2.@Pointcut注解要求配置在方法上方,("execution(void com.lcyy.dao.BookDao.read())")为切入点表达式,execution为关键字,
void为返回值 com.lcyy.dao.BookDao.read()为com.lcyy包下的dao包下的BookDao接口中的read()方法。
3.@Before("pc()") 其中@Before为前置通知,表示为在方法执行前执行。关于通知的几种类型,下面会详细讲解。其中 "pc()" 表示将连接点和通知捆绑起来,注意方法名必须相同。
2.4在配置类中进行Spring注解包扫描和开启AOP功能
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.lcyy")
@EnableAspectJAutoProxy//开启aop
public class SpringConfig {
}
其中注解 @EnableAspectJAutoProxy 表示开启AOP通知,交给IOC容器管理
2.5定义测试类测试结果
import com.lcyy.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class BookDaoTest {public static void main(String[] args) {//获取容器ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.read();}
}
测试结果:

三:AOP工作流程
Spring容器启动
读取所有切面配置中的切入点
初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
匹配失败,创建原始对象
匹配成功,创建原始对象(目标对象)的代理对象
获取bean执行方法
获取的bean是原始对象时,调用方法并执行,完成操作
获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
验证AOP的代理对象,在刚才测试类中获取
import com.lcyy.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class BookDaoTest {public static void main(String[] args) {//获取容器ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.read();System.out.println(bookDao.getClass());}
}
测试结果:

其中:class com.sun.proxy.$Proxy19 就是为代理对象的类名
四:AOP的切入点表达式
4.1语法格式
描述方法一:执行com.lcyy.dao包下的BookDao接口中的无参数read方法
execution(void com.lcyy.dao.BookDao.read())
描述方法二:执行com.lcyy.dao包下的BookDaoImpl实现类中的无参数read方法
execution(void com.lcyy.dao.BookDaoImpl.read())
切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)
execution(public User com.itheima.service.UserService.findById(int))
其中:
动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
访问修饰符:public,private等,可以省略
返回值:写返回值类型
包名:多级包使用点连接
类/接口名:
方法名:
参数:直接写参数的类型,多个类型用逗号隔开
异常名:方法定义中抛出指定异常,可以省略
4.2通配符
(*):单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
(..):多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
常用的通配符表达式为:
@Pointcut("execution(* com.lcyy.dao.*.*(..)")
表示任意的访问修饰符 在com.lcyy.dao包下的任意类中的所有方法(..)表示可以有形参也可以没有形参。
五:AOP通知类型
AOP通知共分为5种类型
前置通知:在切入点方法执行之前执行
后置通知:在切入点方法执行之后执行,无论切入点方法内部是否出现异常,后置通知都会执行。
环绕通知(重点):手动调用切入点方法并对其进行增强的通知方式。
最终通知:在切入点方法执行之后执行,如果切入点方法内部出现异常将不会执行。
异常通知:在切入点方法执行之后执行,只有当切入点方法内部出现异常之后才执行。
5.1前置通知
-
名称:@Before
-
类型:==方法注解==
-
位置:通知方法定义上方
-
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
-
案例代码:
//前置通知@Before("execution(void com.lcyy.dao.BookDao.write())")public void testAdvice2(){System.out.println("我是前置通知");}
5.2后置通知
-
名称:@AfterReturning
-
类型:==方法注解==
-
位置:通知方法定义上方
-
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
-
案例代码:
@AfterReturning("execution(void com.lcyy.dao.BookDao.write())")public void testAdvice4(){System.out.println("我是后置通知");}
5.3最终通知
-
名称:@After
-
类型:==方法注解==
-
位置:通知方法定义上方
-
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
-
案例代码:
@After("execution(void com.lcyy.dao.BookDao.write())")public void testAdvice3(){System.out.println("我是最终通知");}
5.4异常通知
-
名称:@AfterThrowing
-
类型:==方法注解==
-
位置:通知方法定义上方
-
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行
@AfterThrowing("execution(void com.lcyy.dao.BookDao.write())")public void testAdvice5(){System.out.println("我是异常通知");}
在以上四个通知后,我们在测试类中测试以上通知

注意:书写了异常通知,却没有执行,是因为简单的代码实现没有异常。
测试异常通知:
在BookDaoImpl 的实现类中书写测试异常的代码
@Overridepublic void write() {System.out.println("BookDao AOP 实现");int a = 10/0;System.out.println("a = " + a);}
测试结果:

5.5环绕通知
-
名称:@Around(重点,常用)
-
类型:==方法注解==
-
位置:通知方法定义上方
-
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
-
案例代码:
@Around("execution(void com.lcyy.dao.BookDao.jiyi())")public Object testJiyi(ProceedingJoinPoint PJ) throws Throwable {System.out.println("我时前置通知");Object Oj = PJ.proceed();System.out.println("我是后置通知");return Oj;}
测试结果:
注意:
环绕通知方法形参必须是ProceedingJoinPoint,表示正在执行的连接点,使用该对象的proceed()方法表示对原始对象方法进行调用,返回值为原始对象方法的返回值。
环绕通知方法的返回值建议写成Object类型,用于将原始对象方法的返回值进行返回,哪里使用代理对象就返回到哪里。
六:总结
AOP在spring中是一个很重要的概念,理解和运用AOP在以后的业务开发中有很重要的作用!
相关文章:
Spring-AOP
目录 一:什么是AOP 二:AOP快速入门 2.1导入AOP坐标 2.2定义dao接口和实现类 2.3定义通知类 2.4在配置类中进行Spring注解包扫描和开启AOP功能 2.5定义测试类测试结果 三:AOP工作流程 四:AOP的切入点表达式 4.1语法格…...
算法程序设计-快速排序
快速排序采用---分治策略 L |------x-------------| R 第一步确定分界点:q[l],q[(lr)/2],q[r]随机 第二步调整范围:L |--------<x|>x------------| R 第三步递归处理左右两端 两种做法: 第一种:暴力解决 另外定义两个…...
Jmeter用jdbc实现对数据库的操作
我们在用Jmeter进行数据库的操作时需要用到配置组件“JDBC Connection Configuration”,通过配置相应的驱动能够让我们通过Jmeter实现对数据库的增删改查,这里我用的mysql数据库一起来看下是怎么实现的吧。 1.驱动包安装 在安装驱动之前我们要先查看当前…...
Mac 上安装多版本的 JDK 且实现 自由切换
背景 当前电脑上已经安装了 jdk8; 现在再安装 jdk17。 期望 完成 jdk17 的安装,并且完成 环境变量 的配置,实现自由切换。 前置补充知识 jdk 的安装路径 可以通过查看以下目录中的内容,确认当前已经安装的 jdk 版本。 cd /Library/Java/Java…...
springboot如何发送邮件,java如何发送邮件随机码作为验证
maven <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version></dependency> 然后java package com.metasoft.common.utils;import java.util.Properties;import javax.…...
使用QLoRA在自定义数据集上finetuning 大模型 LLAMA3 的数据比对分析
概述: 大型语言模型(LLM)展示了先进的功能和复杂的解决方案,使自然语言处理领域发生了革命性的变化。这些模型经过广泛的文本数据集训练,在文本生成、翻译、摘要和问答等任务中表现出色。尽管LLM具有强大的功能,但它可能并不总是与特定的任务或领域保持一致。 什么是LL…...
编译和链接(超详细)
✅博客主页:爆打维c-CSDN博客 🐾 🔹分享c语言知识及代码 一、编译和链接实例 假设我们有一个名为main.c的C语言源文件,它包含了一个简单的Hello World程序。我们可以使用gcc编译器对该源文件进行编译,生成一个可执行…...
Rust Turbofish 的由来
0x01 什么是 Turbofish 我们运行如下 Rust Snippet: fn main() {let numbers: Vec<i32> vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];let even_numbers numbers.into_iter().filter(|n| n % 2 0).collect();println!("{:?}", even_numbers); }不出意…...
2.外卖点餐系统(Java项目 springboot)
目录 0.系统的受众说明 1.系统功能设计 2.系统结构设计 3.数据库设计 3.1实体ER图 3.2数据表 4.系统实现 4.1用户功能模块 4.2管理员功能模块 4.3商家功能模块 4.4用户前台功能模块 4.5骑手功能模块 5.相关说明 新鲜运行起来的项目:如需要源码数据库…...
Universal Thresholdizer:将多种密码学原语门限化
参考文献: [LS90] Lapidot D, Shamir A. Publicly verifiable non-interactive zero-knowledge proofs[C]//Advances in Cryptology-CRYPTO’90: Proceedings 10. Springer Berlin Heidelberg, 1991: 353-365.[Shoup00] Shoup V. Practical threshold signatures[C…...
【UE5学习笔记】编辑及运行界面:关闭眼部识别(自动曝光)
自动曝光,也就是走进一个黑暗的环境,画面会逐渐变量,以模拟人眼进入黑暗空间时瞳孔放大,进光量增加的一种真实视觉感受: 制作过程中是否关闭自动曝光,取决于游戏的性质,但是个人认为,…...
未来科技的前沿:深入探讨人工智能的进展、机器学习技术和未来趋势
文章目录 一、人工智能的定义和概述1. 人工智能的基本概念2. 人工智能的发展历史 二、技术深入:机器学习、深度学习和神经网络1. 机器学习2. 深度学习3. 神经网络 三、人工智能的主要目标和功能1. 自动化和效率提升2. 决策支持和风险管理3. 个性化服务和预测未来 本…...
3-qt综合实例-贪吃蛇的游戏程序
引言: 如题,本次实践课程主要讲解贪吃蛇游戏程序。 qt贪吃蛇项目内容: 一、功能需求 二、界面设计 各组件使用: 对象名 类 说明 Widget QWidge 主窗体 btnRank QPushButton 排行榜-按钮 groupBox QGroupBox 难…...
QGraphicsView实现简易地图12『平移与偏移』
前文链接:QGraphicsView实现简易地图11『指定层级-定位坐标』 提供地图平移与偏移功能。地图平移是指将地图的中心点更改为给定的点,即移动地图到指定位置。地图偏移是指将当前视口内的地图向上/下/左/右/进行微调,这里偏移视口宽/高的四分之…...
深入探索 Vue 中的 createVNode 与 resolveComponent
在 Vue 开发中,createVNode和resolveComponent是两个至关重要的工具,它们为我们提供了强大的能力来灵活地创建和操控组件。 一、首先,让我们深入了解一下createVNode。 这是一个用于创建虚拟节点的关键函数,通过它,我…...
【记录42】centos 7.6安装nginx教程详细教程
环境:腾讯云centos7.6 需求:安装nginx-1.24.0 1. 切入home文件 cd home 2. 创建nginx文件 mkdir nginx 3. 切入nginx文件 cd nginx 4. 下载nginx安装包 wget https://nginx.org/download/nginx-1.24.0.tar.gz 5. 解压安装包 tar -zxvf nginx-1.24.0.…...
C语言程序设计(不熟悉的点)
一、switch多路分支语句 二、条件表达式 三、循环 for循环: for循环的三个表达式不是必须的,第一个表达式之前声明过,可以不写,第三个表达式可以放在循环体里面;第二个表达式可以不写,为死循环。 空循环…...
DAO是什么?有什么用途?
DAO(Decentralized Autonomous Organization,去中心化自治组织)是一种基于区块链技术的组织形式,它没有中央管理层,而是通过智能合约和区块链上的代码来运作。DAO 的决策过程是透明的,通常由组织的成员通过…...
Socket学习记录
本次学习Socket的编程开发,该技术在一些通讯软件,比如说微信,QQ等有广泛应用。 网络结构 这些都是计算机网络中的内容,我们在这里简单回顾一下: UDP(User Datagram Protocol):用户数据报协议;TCP(Transmission Contr…...
黑马 - websocket搭建在线聊天室
这里写自定义目录标题 一、消息推送常见方式二、websocket 是什么?三、websocket api的介绍1、客户端 (浏览器)2、服务端api 四、实现在线聊天室1、需求2、聊天室流程分析3、消息格式4、代码实现 一、消息推送常见方式 1、轮训方式 2、SSE…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
