3 - AOP

1. 快速入门

1.1 基本说明

AOP(aspect oriented programming) ,面向切面编程

切面类中声明通知方法:

  • 前置通知:@Before
  • 返回通知:@AfterReturning
  • 异常通知:@AfterThrowing
  • 后置通知:@After
  • 环绕通知:@Around

1.2 快速入门 

参考视频:B站 三更草堂视频

1.3 细节说明

1)切面类方法命名

  • showBeginLog()
  • showSuccessEndLog()
  • showExceptionLog()
  • showFinallyEndLog()

2)切入表达式更多的配置

使用模糊配置

@Before(value="execution(* com.hspedu.aop.proxy.SmartDog.*(..))")

这个就表示这个切面方法作用与  com.hspedu.aop.proxy.SmartDog 类的函数

3)所有访问权限

@Before(value="execution(* *.*(..))")
  1. 第一个 * 表示 任意方法权限及任意返回值
  2. 第二个 * 表示 任意路径
  3. 第三个 * 表示 任意方法
  4. (..) 表示任意数量,任意类型的参数

所有包的下所有有类的所方法,都会被执行该前置通知方法

4)使用基于注解的AOP需要在配置文件里开启

<aop:aspectj-autoproxy/> 

5)开启了基于注解的后获取对象

这个时候去获取 ioc 容器里的对象的话,在底层被转换为 代理对象

我们获取注入的对象, 也可以通过 id 来获取, 但是也要转成接口类型


2. AOP-切入表达式

2.1 具体使用

1)作用

通过表达式的方式来定位一个或多个具体的切入点

2)语法细节

格式: execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名] ([参数列表]))

若目标类、接口 与切面类在同一个包下,可以省略包名

2.2 注意事项和细节

1)表达式指向类

切入表达式也可以指向类的方法, 这时切入表达式会对该类/对象生效

2)表达式指向接口

切入表达式也可以指向接口的方法, 这时切入表达式会对实现了接口的类/对象生效

3)表达式指向没有实现接口的类

切入表达式也可以对没有实现接口的类,进行切入

@Component
class Car {public void run() {System.out.println("car run");}
}

切面类:

@Before(value = "execution(public void com.hspedu.spring.aop.aspectj.Car.run())")public static void showBeginLog3(JoinPoint joinPoint) {//获取方法签名Signature signature = joinPoint.getSignature();System.out.println("方法执行前--方法名--" + signature.getName());}

测试:

@Testpublic void carTestProxy() {//得到spring容器ApplicationContext ioc = new ClassPathXmlApplicationContext("beans08.xml");Car car = ioc.getBean(Car.class);System.out.println(car.getClass());car.run();}

不一样的时,这此取出来的 car 对象的运行类型:

    class com.hspedu.spring.aop.aspectj.Car$$EnhancerBySpringCGLIB$$8e9f1fa7

这个时候 就是 Spring 的 CGlib 方案:取出的时 Car 对象的子类

参考:jdk的Proxy与spring的CGlib


3. 切入方法细节

3.1 AOP-JoinPoint 

常用方法一览

  • joinPoint.getSignature().getName(); 获取目标方法名
  • joinPoint.getSignature().getDeclaringType().getSimpleName(); 获取目标方法所属类的简单类名
  • joinPoint.getSignature().getDeclaringTypeName();  获取目标方法所属类的类名
  • joinPoint.getSignature().getModifiers(); /获取目标方法声明类型(public、private、protected)
  • Object[] args = joinPoint.getArgs();  获取传入目标方法的参数,返回一个数组
  • joinPoint.getTarget();   获取被代理的对象
  • joinPoint.getThis();    获取代理对象自己

3.2 返回通知获知结果

如何在返回通知方法获取返回结果?

**
* returning = "res", Object res 名称保持一致
* @param joinPoint
* @param res 调用 getSum() 返回的结果
*/
@AfterReturning(value="execution(public float com.hspedu.spring.aop.joinpoint.SmartDog.getSum(float, float))",returning = "res")
public void showSuccessEndLog(JoinPoint joinPoint, Object res) {System.out.println("返回通知" + "--结果是--" + res );
}

3.3 AOP-异常通知中获取异常

@AfterThrowing(value="execution(public float
com.hspedu.spring.aop.joinpoint.SmartDog.getSum(float, float))",throwing = "throwable")
public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {System.out.println("异常通知 -- 异常信息--" + throwable);
}

3.4 环绕通知(了解)

环绕通知可以完成其它四个通知要做的事情

@Aspect //表示这个类是一个切面类
@Component //需要加入到 IOC 容器
public class SmartAnimalAspect {//=====环绕通知 start=====//@Around(value = "execution(* *.*(..))")@Around(value="execution(public floatcom.hspedu.spring.aop.joinpoint.SmartDog.getSum(float, float))")public Object doAround(ProceedingJoinPoint joinPoint) {Object result = null;String methodName = joinPoint.getSignature().getName();try {//1.相当于前置通知完成的事情Object[] args = joinPoint.getArgs();List<Object> argList = Arrays.asList(args);System.out.println("AOP 环绕通知--" + methodName + "开始了--参数有:" + argList);//在环绕通知中一定要调用 joinPoint.proceed()来执行目标方法result = joinPoint.proceed();//2.相当于返回通知完成的事情System.out.println("AOP 环绕通知" + methodName + "结束了--结果是:"+ result);} catch (Throwable throwable) {//3.相当于异常通知完成的事情System.out.println("AOP 环绕通知" + methodName + "抛异常--异常对象:" + throwable);} finally {//4.相当于最终通知完成的事情System.out.println("AOP 后置通知" + methodName + "最终结束...");}return result;
}

环绕通知和动态代理完成的事情相似

3.5  切入点表达式重用

为了统一管理切入点表达式,可以使用切入点表达式重用技术

在切面类上添加:

//=====AOP-切入点表达式重用 start ======
/*
* 这样定义的一个切入点表达式,就可以在其它地方直接使用
*/
@Pointcut(value="execution(public float
com.hspedu.spring.aop.joinpoint.SmartDog.getSum(float, float))")
public void myPointCut() {
}

这样其他切面方法就可以简写:

@Before(value = "myPointCut()")
public void showBeginLog(JoinPoint joinPoint) { //前置方法Signature signature = joinPoint.getSignature();//得到方法名.String method_name = signature.getName();//得到参数Object[] args = joinPoint.getArgs();System.out.println("前置通知" + "--调用的方法是 " + method_name + "--参数是--" + Arrays.asList(args));
}

3.6 AOP-切面优先级问题

如果同一个方法,有多个切面在同一个切入点切入,那么执行的优先级如何控制?

@order(value=n) 

通过设定 order 的value 值来控制, n 值越小,优先级越高

@Aspect //表示这个类是一个切面类
@Order(value = 2)
@Component //需要加入 IOC 容器
public class SmartAnimalAspect2 {/**内部是切面方法*/
}/****************************/@Aspect //表示这个类是一个切面类
@Order(value = 1)
@Component //需要加入 IOC 容器
public class SmartAnimalAspect {/**内部是切面方法*/
}

输出的信息顺序,类似 Filter 的过滤链式调用机制


3.  基于 XML 配置 AOP

前面是通过注解来配置 aop 的,在 spring 中,我们也可以通过 xml 的方式来配置 AOP

1)准备对象

去掉切面方法的所有注解

2)配置 xml

<!-- 配置 SmartAnimalAspect bean -->
<bean id="smartAnimalAspect" class="com.hspedu.spring.aop.xml.SmartAnimalAspect"/><!--配置 SmartDog-->
<bean class="com.hspedu.spring.aop.xml.SmartDog" id="smartDog"/><aop:config><!-- 配置统一切入点 --><aop:pointcut expression="execution(public floatcom.hspedu.spring.aop.xml.SmartDog.getSum(float, float))" id="myPointCut"/><aop:aspect ref="smartAnimalAspect" order="1"><!-- 配置各个通知对应的切入点 --><aop:before method="showBeginLog" pointcut-ref="myPointCut"/><aop:after-returning method="showSuccessEndLog" pointcut-ref="myPointCut" returning="res"/><aop:after-throwing method="showExceptionLog" pointcut-ref="myPointCut" throwing="throwable"/><aop:after method="showFinallyEndLog" pointcut-ref="myPointCut"/><!-- 还可以配置环绕通知 --><!-- <aop:around method=""/> --></aop:aspect>
</aop:config>

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

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

相关文章

2、Redis持久化、主从与哨兵:构建强大而稳定的数据生态

Redis作为一款高性能的内存数据库&#xff0c;其在持久化、主从复制和哨兵系统方面的支持使其在大规模应用和高可用性场景中脱颖而出。本文将深入探讨Redis的持久化机制、主从复制以及哨兵系统&#xff0c;为构建强大而稳定的数据生态揭示关键技术。 持久化&#xff1a;数据的…

http状态码对照表

状态码含义100客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收&#xff0c;且仍未被拒绝。客户端应当继续发送请求的剩余部分&#xff0c;或者如果请求已经完成&#xff0c;忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应。…

开发React应用的多语言支持最佳实践

前言 VoerkaI18n是一款非常优秀的全新的开源国际化多语言解决方案&#xff0c;主要特性包括&#xff1a; 全面工程化解决方案&#xff0c;提供初始化、提取文本、自动翻译、编译等工具链支持。符合直觉&#xff0c;不需要手动定义文本Key映射。强大的插值变量格式化器机制&am…

二进制与十六进制,二进制与八进制之间的相互转换技巧

目录 1.二进制转换为八进制 2.八进制转换为二进制 3.二进制转换为十六进制 4.十六进制转换为二进制 1.二进制转换为八进制 转换为8进制 第一步&#xff1a;以小数点为分界线&#xff0c;整数部分自右向左&#xff0c;小数部分自左向右每3位取成1位&#xff1a; 整数部分…

【python入门】day28:记录用户登录日志

演示 代码 #-*- coding:utf-8 -*- print(记录用户登录日志----------------------------) import time def show_info():print(输入提示数字,执行相应操作:0退出,1查看登录日志) def write_logininfo(username):#----------记录日志with open(log.txt,a,encodingutf-8)as file…

如何高效阅读Linux的man page

有时候需要在man page中查某个命令的用法&#xff0c;我们一般会使用man command的方式来查询&#xff0c;例如man vmstat.但是对于一些bash内置的命令&#xff0c;如alias,如果使用man alias会打开General Commands Manual ,如下图 可以看到&#xff0c;内置命令很多&#xff…

COBOL语言 :一种主要专注于解决业务问题的编程语言

译文&#xff1a; 什么是COBOL? COBOL是一种主要专注于解决业务问题的编程语言。COBOL的完整形式是面向业务的通用语言。它主要用于公司和政府的商业、金融和行政系统。这种语言也被用来解决许多数据处理问题。 它是由CODASYL(数据系统语言会议)开发的。它被用作大型机中的一…

基于 InternLM 和 LangChain 搭建你的知识库

如何打造垂域大模型是一个重要落地方向。 如何打造个人专属的大模型应用也是重要的问题。 RAG 外挂一个知识库 优势&#xff1a;成本低&#xff0c;实时更新 劣势&#xff1a;能力受基座模型影响大&#xff0c;RAG每次需要将检索文档和问题提交给大模型&#xff0c;极大占用上下…

工程项目管理系统源码与Spring Cloud:实现高效系统管理与二次开发

随着企业规模的不断扩大和业务的快速发展&#xff0c;传统的工程项目管理方式已经无法满足现代企业的需求。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;企业需要借助先进的数字化技术进行转型。本文将介绍一款采用Spring CloudSpring BootMybat…

C++力扣题目701--二叉搜索树中的插入操作

给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&#xff0c;可能存在多种有效的插入方式&a…

苏州倍丰智能新型雾化粉末技术量产成功!金属3D打印全产业链更进一步

苏州倍丰智能深耕金属3D打印技术领域&#xff0c;以金属3D打印全产业链为目标&#xff0c;围绕金属3D打印设备&#xff0c;涵盖包括金属粉末前后处理设备、金属粉末原材料制备、先进工艺研发等多个领域&#xff0c;完成了一整条自上而下的金属3D打印全产业链。 近日&#xff0c…

大数据Doris(五十四):SQL函数之日期函数(二)

文章目录 SQL函数之日期函数(二) 一、DAYOFMONTH(DATETIME date) 二、dayofweek(DATETIME date)

HarmonyOS 通过 animateTo讲解尺寸动画效果

上文 HarmonyOS讲解并演示 animateTo 动画效果 我们已经做出了基本的动画效果 也对 animateTo 的使用比较熟悉了 第一个参数是 配置动画参数的json 第二个参数 则是改变我们元素属性值的事件 但属性值 远远不止位置属性 本文 我们来说 通过尺寸变化 完成动画效果 如果你有看过…

代码随想录算法训练营第4天 | 24. 两两交换链表中的节点 , 19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交 , 142.环形链表II

链表知识基础 文章链接&#xff1a;https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html# 24. 两两交换链表中的节点 题目链接&#xff1a;https://leetcode.cn/problems/swap-nodes-in-pairs/ 使用虚拟头结点&#xff0c;这样会方便很…

Promise和箭头函数和普通函数的区别

\1. Promise 的理解 Promise 是一种为了避免回调地狱的异步解决方案 2. Promise 是一种状态机&#xff1a; pending&#xff08;进行中&#xff09;、fulfilled&#xff08;已成功&#xff09;和rejected&#xff08;已失败&#xff09; 只有异步操作的结果&#xff0c;可以决…

Centos7编译Python3.11源码并安装完成的详细教程

Python3.11的Linux源码&#xff1a; Index of /ftp/python/https://www.python.org/ftp/python/由于Centos7里自带的openssl是1.0版本的&#xff0c;而Centos Stream8和9用的是openssl-1.1.1版本的。 注意&#xff1a;openssl必须是openssl-1.1.1版本的&#xff0c;虽然最高版…

QT的事件机制

QT的事件机制 文章目录 QT的事件机制 1、QT的事件机制。2、QT事件的整体流程。1、事件处理函数。1、鼠标按下与鼠标释放事件。2、事件的接收与忽略(accept()和ignore()函数&#xff09;。 2.事件的分发enevt()1、事件分发的dome。2、enevt事件的缺点。 3、事件的过滤器。 3、总…

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客&#xff0c;当时作为一名技术小菜鸟&#xff0c;总体而言显得很拙见&#xff0c;但也算是成长路上的一个小脚印&#xff0c;希望能在以后的日子里&#xff0c;可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

自学习算法

自学习算法是一种基于深度学习的技术&#xff0c;通过大量的数据和模型训练&#xff0c;不断优化和改进模型的表现。 具体来说&#xff0c;自学习算法包括以下几个方面&#xff1a; 1.数据预处理&#xff1a;在训练模型之前&#xff0c;需要对大量的数据进行清洗、去重、标注…