【Spring教程17】Spring框架实战:实例详解解读AOP通知类型的使用

news2024/11/24 14:39:19

欢迎大家回到《Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《AOP配置管理中AOP切入点表达式和通知类型》

在这里插入图片描述

本文的示例代码均来自之前AOP的相关博博文,没有示例代码的C友,请移步《Spring教程13》开始看起

1、前置通知

修改MyAdvice,在before方法上添加@Before注解

@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Before("pt()")
	//此处也可以写成 @Before("MyAdvice.pt()"),不建议
	public void before() {
		System.out.println("before advice ...");
	}
}

在这里插入图片描述

2、后置通知

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Before("pt()")
	public void before() {
		System.out.println("before advice ...");
	}
	@After("pt()")
	public void after() {
		System.out.println("after advice ...");
	}
}

在这里插入图片描述

3、环绕通知

基本使用

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Around("pt()")
	public void around(){
		System.out.println("around before advice ...");
		System.out.println("around after advice ...");
	}
}

在这里插入图片描述
运行结果中,通知的内容打印出来,但是原始方法的内容却没有被执行。

因为环绕通知需要在原始方法的前后进行增强,所以环绕通知就必须要能对原始操作进行调用,具体
如何实现?

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Around("pt()")
	public void around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("around before advice ...");
		//表示对原始操作的调用
		pjp.proceed();
		System.out.println("around after advice ...");
	}
}

**说明:**proceed()为什么要抛出异常?
原因很简单,看下源码就知道了
在这里插入图片描述
再次运行,程序可以看到原始方法已经被执行了
在这里插入图片描述
注意事项
(1)原始方法有返回值的处理

  • 修改MyAdvice,对BookDao中的select方法添加环绕通知,
@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Pointcut("execution(int com.itheima.dao.BookDao.select())")
	private void pt2(){}
	@Around("pt2()")
	public void aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("around before advice ...");
		//表示对原始操作的调用
		pjp.proceed();
		System.out.println("around after advice ...");
	}
}
  • 修改App类,调用select方法
public class App {
	public static void main(String[] args) {
	ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
		BookDao bookDao = ctx.getBean(BookDao.class);
		int num = bookDao.select();
		System.out.println(num);
	}
}

运行后会报错,错误内容为:
Exception in thread “main” org.springframework.aop.AopInvocationException:
‘Null return value from advice does not match primitive return type for:
public abstract int com.itheima.dao.BookDao.select()’ at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:226) at com.sun.proxy.$Proxy19.select(Unknown Source) at com.itheima.App.main(App.java:12)

错误大概的意思是:空的返回不匹配原始方法的int返回

  • void就是返回Null
  • 原始方法就是BookDao下的select方法

所以如果我们使用环绕通知的话,要根据原始方法的返回值来设置环绕通知的返回值,具体解决方案
为:

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	
	@Pointcut("execution(int com.itheima.dao.BookDao.select())")
	private void pt2(){}
	
	@Around("pt2()")
	 public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("around before advice ...");
		//表示对原始操作的调用
		Object ret = pjp.proceed();
		System.out.println("around after advice ...");
		return ret;
	}
}

说明:
为什么返回的是Object而不是int的主要原因是Object类型更通用。
在环绕通知中是可以对原始方法返回值就行修改的。
返回后通知

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Pointcut("execution(int com.itheima.dao.BookDao.select())")
	private void pt2(){}
	@AfterReturning("pt2()")
	public void afterReturning() {
		System.out.println("afterReturning advice ...");
	}
}

在这里插入图片描述
**注意:**返回后通知是需要在原始方法select正常执行后才会被执行,如果select()方法执行的过程
中出现了异常,那么返回后通知是不会被执行。后置通知是不管原始方法有没有抛出异常都会被执
行。这个案例大家下去可以自己练习验证下。
异常后通知

@Component
@Aspect
public class MyAdvice {
	@Pointcut("execution(void com.itheima.dao.BookDao.update())")
	private void pt(){}
	@Pointcut("execution(int com.itheima.dao.BookDao.select())")
	private void pt2(){}
	@AfterReturning("pt2()")
	public void afterThrowing() {
		System.out.println("afterThrowing advice ...");
	}
}

在这里插入图片描述
**注意:**异常后通知是需要原始方法抛出异常,可以在select()方法中添加一行代码int i = 1/0即可。如果没有抛异常,异常后通知将不会被执行。
学习完这5种通知类型,我们来思考下环绕通知是如何实现其他通知类型的功能的?
因为环绕通知是可以控制原始方法执行的,所以我们把增强的代码写在调用原始方法的不同位置就可以实现不同的通知类型的功能,如:
在这里插入图片描述

4、通知类型总结

知识点1:@After
在这里插入图片描述
知识点2:@AfterReturning
在这里插入图片描述
知识点3:@AfterThrowing
在这里插入图片描述
知识点4:@Around
在这里插入图片描述
环绕通知注意事项

  1. 环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法
    调用前后同时添加通知
  2. 通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行
  3. 对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,最好设定为
    Object类型
  4. 原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成
    Object
  5. 由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须要处理Throwable异常
    介绍完这么多种通知类型,具体该选哪一种呢?
    下一章节,我们可以通过一些案例加深下对通知类型的学习

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

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

相关文章

Python:核心知识点整理大全13-笔记

目录 6.4.3 在字典中存储字典 6.5 小结 第7章 用户输入和while循环 7.1 函数 input()的工作原理 7.1.1 编写清晰的程序 7.1.2 使用 int()来获取数值输入 7.1.3 求模运算符 7.1.4 在 Python 2.7 中获取输入 7.2 while 循环简介 7.2.1 使用 while 循环 往期快速传送门…

机器学习与人工智能:一场革命性的变革

机器学习与人工智能:一场革命性的变革 人工智能的概述什么是机器学习定义解释 数据集结构机器学习应用场景 人工智能的概述 1956年8月,在美国汉诺斯小镇宁静的达特茅斯学院中,约翰麦卡锡(John McCarthy)、马文闵斯基&…

SDXL使用animateDiff和hotshot-xl进行文生视频

截至2023.12.8号,目前市面上有两款适用于SDXL的文生视频开源工具,分别是AnimateDiff和hotshot-xl。 一、工具下载链接 (1)AnimateDiff的webui版本的git链接: GitHub - continue-revolution/sd-webui-animatediff: A…

前端 usbkey navigator.usb 登录检测

前端 usbkey navigator.usb 实现登录 前言调用api 报错总结 前言 navigator.usb 是一个与USB设备交互的API,它允许网页和浏览器扩展程序访问连接到电脑的USB设备。这个API可以让网页直接与USB设备进行数据交换,而无需用户手动安装任何软件。navigator.u…

【计算机网络实验】实验三 IP网络规划与路由设计(头歌)

目录 一、知识点 二、实验任务 三、头歌测试 一、知识点 IP子网掩码的两种表示方法 32位IP子网掩码,特点是从高位开始连续都是1,后面是连续的0,它有以下两种表示方法: 传统表示法,如:255.255.255.0IP前…

四年成长总结

树叶绿了又落下,树叶落下又绿了……季节如此,时间依然。 每到快结束的时候,总是不免的使人伤怀起来,可能是昨天的昨天仍旧使人“忆”,明天的未知使人“追”,不论是昨天亦或是明天,“斯为泰山而…

如何进行落地的数据分析,并提出落地的分析建议?

落地的数据分析是指将数据分析结果应用到实际业务中,以提供有价值的决策支持和改进方案。在进行落地的数据分析前,需要明确分析目标和需求,制定合适的分析方法和步骤,并在分析过程中不断优化和验证分析结果。以下是进行落地的数据…

AI PC行业深度研究报告:AI PC革新端侧AI交互体验

今天分享的人工智能系列深度研究报告:《AI PC行业深度研究报告:AI PC革新端侧AI交互体验》。 (报告出品方:华创证券) 报告共计:28页 点击添加图片描述(最多60个字)编辑 一、硬件端…

爬虫 selenium语法 (八)

目录 一、为什么使用selenium 二、selenium语法——元素定位 1.根据 id 找到对象 2.根据标签属性的属性值找到对象 3.根据Xpath语句获取对象 4.根据标签名获取对象 5.使用bs语法获取对象 6.通过链接文本获取对象 三、selenium语法——访问元素信息 1.获取属性的属性值…

Leetcode—228.汇总区间【简单】

2023每日刷题&#xff08;五十六&#xff09; Leetcode—228.汇总区间 解题思路 我们可以用双指针left 和 right找出每个区间的左右端点。 遍历数组&#xff0c;当right 1< n 且 nums[right1]nums[right]1 时&#xff0c;指针right向右移动&#xff0c;否则区间 [left, …

15:00面试,15:06就出来了,问的问题太变态了。。

刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到5月一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资还要降…

成都工业学院Web技术基础(WEB)实验八:BOM、DOM基本操作

写在前面 1、基于2022级计算机大类实验指导书 2、代码仅提供参考&#xff0c;前端变化比较大&#xff0c;按照要求&#xff0c;只能做到像&#xff0c;不能做到一模一样 3、图片和文字仅为示例&#xff0c;需要自行替换 4、如果代码不满足你的要求&#xff0c;请寻求其他的…

c2-C语言--指针

1.用一级指针遍历一维数组 结论 buf[i]<>*(buf i) <> *(p i)<> p[i] #include <stdio.h>int main(){int buf[5] {10,20 ,30 ,40,50}; //buf[0] --- int // buf --&buf[0] ----int *int *p buf;//&buf[0] --- &*(buf0)printf(&quo…

声明式数据建模、定义简单易懂:下一代 ORM 助你效率倍增 | 开源日报 No.102

prisma/prisma Stars: 34.0k License: Apache-2.0 Prisma 是一个下一代 ORM&#xff0c;包括以下工具&#xff1a; Prisma Client&#xff1a;为 Node.js 和 TypeScript 自动生成的类型安全查询构建器Prisma Migrate&#xff1a;声明式数据建模和迁移系统Prisma Studio&#…

【解刊】IEEE(trans),CCF-A,IF7.9,潜力好刊

计算机类 • 好刊解读 今天小编带来IEEE旗下计算机领域高分好刊&#xff0c;CCF-A类推荐的期刊解读&#xff0c;如您有投稿需求&#xff0c;可作为重点关注&#xff01;后文有相关领域真实发表案例&#xff0c;供您投稿参考~ 01 期刊简介 IEEE Transactions on Mobile Compu…

科研试剂2913223-17-1激酶抑制剂 KWCN-41

KWCN-41 激酶抑制剂 2913223-17-1&#xff08;源自星戈瑞&#xff09; EFdA-TP 核苷逆转录酶抑制剂 950913-56-1 (RT) 3-O-Methylviridicatin TNF-α的抑制剂 6152-57-4 Zidebactam sodium salt β-内酰胺酶抑制剂 1706777-46-9 Triacsin C 酰基辅酶A合成酶抑制剂 76896-80…

【lesson4】数据类型之数值类型

文章目录 数据分类数值类型tinyint类型有符号类型测试无符号类型测试 bit类型测试 float类型有符号测试无符号测试 decimal类型测试 数据分类 数值类型 tinyint类型 说明&#xff1a;tinyint 有符号能存储的范围是-128-127&#xff0c;无符号能存储的范围是0~255 有符号类型…

AI 绘画 | Stable Diffusion 艺术二维码制作

前言 这篇文章教会你如果用Stable Diffusion WEB UI制作艺术二维码,什么是艺术二维码呢?就是普通二维码和艺术图片融合后的二维码图片,如下图所示。主要原理还是使用controlNet的control_v1p_sd15_qrcode_monster模型和光影模型control_v1p_sd15_brightness。 教程 准备…

推荐4个优秀的 Python 时间序列分析库

时间序列分析在金融和医疗保健等领域至关重要&#xff0c;在这些领域&#xff0c;理解随时间变化的数据模式至关重要。在本文中&#xff0c;我们将介绍四个主要的Python库——statmodels、tslearn、tssearch和tsfresh——每个库都针对时间序列分析的不同方面进行了定制。这些库…

【每日一题】1631. 最小体力消耗路径-2023.12.11

题目&#xff1a; 1631. 最小体力消耗路径 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) &#xff0c;且你希望去最右下角的格子 (rows-1, column…