当前位置: 首页 > news >正文

Spring之AOP理解及使用

文章目录

      • AOP是什么
      • AOP
        • Spring的通知类型
            • 1.Before通知
            • 2. AfterReturning通知
            • 3.AfterThrowing通知
            • 4. After通知
            • 5. Around通知
        • 动态代理
          • JDK动态代理
          • CGLib动态代理
          • 动态代理的代码展示
      • AOP使用
        • 切面类的配置
      • 最后

大家好,我是Leo!今天给大家带来的是关于Spring AOP的一些知识和动态代理的两种实现方式,以及AOP的使用,希望大家可以喜欢👍👍👍

AOP是什么

AOP:面向切面编程,简单的说,就是把一些业务逻辑中的相同代码抽取到一个独立的模块中,让业务逻辑更加清楚,耦合性更低。

AOP

切面(Aspect):描述的是一个应用系统的某一方面或领域,如日志、事务、权限检查等。切面和类非常相似,对连接点、切入点、通知及类型间声明进行封装。

连接点(Joinpoint):连接点是应用程序执行过程中插入切面的点,这些点可能是方法的调用、异常抛出或字段的修改。Spring只支持方法的Joinpoint,也就是Advice将方法执行的前后被应用

通知(Advice):表示切面的行为,具体表现位实现逻辑的一个方法,常见的方法有Before、After、Around和Throws。Before和After分别表示通知在连接点的前面或者后面执行,Around则表示在连接点的外面执行,并可以决定是否执行此连接点。Throws通知方法抛出异常时执行。

切入点(Pointcut):切入点指定了通知应用在哪些连接点上,Pointcut切点通过正则表达式定义方法集合。切入点由一系列切入点指示符通过逻辑运算组合得到,AspectJ的常用切入点指示符包括execution、call、inititalization、handler、get、set、this、target、args、within等

目标对象(Target): 目标对象是指被通知的对象,它是一个普通的业务对象,如果没有AOP,那么它其中可能包含打量的非核心业务逻辑代码,如日志、事务等;而如果使用了AOP,则其中只有核心的业务逻辑代码。

代理(Proxy):代理是指通知应用到目标对象后形成的新的对象。

织入(Weraving): 织入是指将切面应用到目标对象而建立一个新的代理对象的过程,切面在指定的接入点被织入目标对象中。

Spring的通知类型

1.Before通知

Before通知处理前,该方法还未执行,所以使Before通知无法返回目标方法的值

2. AfterReturning通知

在切点表达式中定义的方法后执行

pointcut/value:这两个属性是一样的,用来指定切入点对呀的切入点表达式,可以是已定义的切入点,也可直接定义切入点表达式

returning:指定一个返回值的形参名,可以通过该形参可访问目标方法的返回值

3.AfterThrowing通知

主要用来处理程序中未处理的异常。使用AfterThrowing通知可指定如下属性。

pointcut/value:用来指定切入点对应的切入点表达式

throwing:指定一个返回形参名,通过该形参访问目标方法抛出但未处理的异常。

4. After通知

与AfterReturning通知非常类似,但是AfterReturning通知只有在目标方法执行完毕才可以被织入

5. Around通知

这个功能比较强大,近似等于Before通知和AfterReturning通知的总合,但是Around通知可以决定目标方法什么时候执行,如何执行。

在定义Around通知的切面逻辑方法时,必须给方法加入ProceedingJoinPoint类型的参数,在方法内调用ProceedingJoinPoint的proceed()方法才会执行目标方法。

优先级由低到高的顺序

Before通知–》Around通知–》AterReturning通知 --》After通知 /AfterThrowing通知

动态代理

动态代理就是,在程序运行期创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。

Spring AOP是通过动态代理实现的,动态代理主要有两种方式JDK动态代理和CGLib动态代理,这两种动态代理的使用和原理有些不同。

JDK动态代理

基于接口的动态代理

  1. 对于JDK代理,目标类需要实现一个Interface

  2. InvocationHandler是一个接口,可以实现这个接口,再通过调用反射机制(invoke)调用目标类的代码

  3. Proxy可以使用newProxyInstance,传入类加载器,目标的接口,InvocationHandler,生成一个动态代理的对象

CGLib动态代理

基于类的动态代理

  1. JDK代理的一大限制是只能为接口创建代理实例,CgLib没有这个限制

  2. CgLib创建的动态代理对象性能比JDK性能要高

  3. CgLib是基于ASM实现,通过字节码技术为一个类创建子类,在子类中采用方法拦截父类方法的调用

两种动态代理的图如下,可以很清楚看出JDK代理是需要实现接口,而CgLib不需要。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7UCAVtP-1677496876494)(D:\卓面\学习文件\学习内容\博客\博客插图\JDK动态代理.drawio.png)]

动态代理的代码展示

JDK动态代理

public class ProxyFactory {private Object target;public ProxyFactory(Object target) {this.target = target;}public Object getProxy() {ClassLoader classLoader = target.getClass().getClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();InvocationHandler invocationHandler = new InvocationHandler() {/**** @param proxy 代理对象* @param method 代理需要实现的方法* @param args 参数* @return 返回值* @throws Throwable 抛出的异常*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 调用目标的方法Object result = null;try {System.out.println("[动态代理][日志] "+ method.getName()+",参数:"+ Arrays.toString(args));result = method.invoke(target, args);System.out.println("[动态代理][日志] "+ method.getName()+",结果:"+ result);} catch (Exception e) {e.printStackTrace();System.out.println("[动态代理][日志] "+ method.getName()+",异常:"+ e.getMessage());} finally {System.out.println("[动态代理][日志] "+ method.getName()+",方法执行完毕");}return result;}};/*** Proxy.newProxyInstance* 三个参数* 1. 加载动态生成代理类来加载的类加载器* 2. interfaces: 目标对象实现的所有接口class类型数组* 3. InvocationHandler 设置代理对象实现对象方法的过程*/return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);}
}

CgLib动态代理

public class ProxyCglibFactory implements MethodInterceptor {private Object target;public ProxyCglibFactory(Object target) {this.target = target;}public Object getProxyInstance() {Enhancer enhancer = new Enhancer();// 设置父类enhancer.setSuperclass(target.getClass());// 设置回调函数enhancer.setCallback(this);// 创建子类对象处理return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 调用目标的方法Object result = null;try {System.out.println("[动态代理][日志] "+ method.getName()+",参数:"+ Arrays.toString(args));result = method.invoke(target, args);System.out.println("[动态代理][日志] "+ method.getName()+",结果:"+ result);} catch (Exception e) {e.printStackTrace();System.out.println("[动态代理][日志] "+ method.getName()+",异常:"+ e.getMessage());} finally {System.out.println("[动态代理][日志] "+ method.getName()+",方法执行完毕");}return result;}
}

AOP使用

AOP切面这些概念的定义是比较抽象的,下面我们来看一下如何使用。

假设一个场景,我有一个计算器类有加减乘除四个方法,我想要打印每一个方法的参数和对应的返回值。

有人就说啦,我每一个System.out.println,或者log.info不就行了嘛,但是加入有一百个方法呢,不断复制CV是不是多余的?

Calculator.java

public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);}
@Component
public class CalculatorImpl implements Calculator {@Overridepublic int add(int i, int j) {int result = i + j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int sub(int i, int j) {int result = i - j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int mul(int i, int j) {int result = i * j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int div(int i, int j) {int result = i / j;System.out.println("方法内部 result = " + result);return result;}
}

切面类的配置

@Component
@Aspect
public class LogAspect {/*** 设置切入点和通知类型* 切入点表达式 execution(访问修饰符 返回值类型 方法所在类的全路径 方法名 参数列表* 通知类型:* 前置@Before* 返回@AfterReturning* 异常@AfterThrowing* 后置@After* 环绕@Around()*/@Before(value = "pointCut()")public void beforeMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("Logger-->前置通知,方法名称:" + methodName + "参数:" + Arrays.toString(args));}@After(value = "pointCut()")public void afterMethod(JoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();System.out.println("Logger-->后置通知,方法名称:" + methodName);}@AfterReturning(value = "pointCut()", returning = "result")public void afterReturningMethod(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();System.out.println("Logger-->返回前置通知,方法名称:" + methodName + "返回值:" + result.toString());}@AfterThrowing(value = "pointCut())", throwing = "exception")public void afterThrowingMethod(JoinPoint joinPoint, Throwable exception) {String methodName = joinPoint.getSignature().getName();System.out.println("Logger-->异常通知,方法名称:" + methodName + "异常:" + exception.toString());}@Around(value = "pointCut()")public Object aroundMethod(ProceedingJoinPoint joinPoint) {String methodName = joinPoint.getSignature().getName();String argsString = joinPoint.getArgs().toString();Object result = null;try {System.out.println("环绕通知");// 调用目标方法result = joinPoint.proceed();System.out.println("环绕通知==目标方法返回值之后");} catch (Throwable ex) {System.out.println("环绕通知==目标方法出现异常之后");} finally {System.out.println("环绕通知==目标方法执行完毕");}return result;}/*** 重用切入点表达式*/@Pointcut(value = "execution(* com.zly.aop.annotation.CalculatorImpl.* (..))")public void pointCut() {}
}

[外链图片转存中...(img-o6Rg7hvZ-1677496876495)]

最后

希望各位大佬指正,点点👍

相关文章:

Spring之AOP理解及使用

文章目录AOP是什么AOPSpring的通知类型1.Before通知2. AfterReturning通知3.AfterThrowing通知4. After通知5. Around通知动态代理JDK动态代理CGLib动态代理动态代理的代码展示AOP使用切面类的配置最后大家好&#xff0c;我是Leo&#xff01;今天给大家带来的是关于Spring AOP的…...

微信小程序和webview使用postMessage交互

小程序和webview能交互&#xff0c;但是没有你想的那个完美小程序向webview传递参数只能使用url携带参数webview向小程序传递参数可以使用postMessage, 但是注意了&#xff0c;postMessage只会在特定的时机执行&#xff0c;请看官方文档由此可见&#xff0c;如果你想点击webvie…...

pytorch-自动求导机制,构建计算图进行反向传播,需要注意inplace操作导致的报错,梯度属性变化

PyTorch 作为一个深度学习平台&#xff0c;在深度学习任务中比 NumPy 这个科学计算库强在哪里呢&#xff1f;一是 PyTorch 提供了自动求导机制&#xff0c;二是对 GPU 的支持。由此可见&#xff0c;自动求导 (autograd) 是 PyTorch&#xff0c;乃至其他大部分深度学习框架中的重…...

【Project】项目管理软件学习笔记

一、前言使用Project制定项目计划步骤大致如下&#xff1a;以Project2013为例&#xff0c;按照上图步骤指定项目计划。二、实施2.1 创建空白项目点击文件——新建——空白项目&#xff0c;即完成了空白项目的创建&#xff0c;在此我把该项目保存为60mm项目管理.mpp&#xff0c;…...

【算法设计-分治思想】快速幂与龟速乘

文章目录1. 快速幂2. 龟速乘3. 快速幂取模4. 龟速乘取模5. 快速幂取模优化1. 快速幂 算法原理&#xff1a; 计算 311&#xff1a; 311 (35)2 x 335 (32)2 x 332 3 x 3仅需计算 3 次&#xff0c;而非 11 次 计算 310&#xff1a; 310 (35)235 (32)2 x 332 3 x 3仅需计算…...

Kafka(十一) 如何保证数据的不重复和不丢失

数据不丢失 1&#xff09;从生产端&#xff1a;acks -1&#xff0c;&#xff08;ack应答机制&#xff09;从生产端到节点端&#xff0c;当所有isr集合里的节点备份完毕后返回成功&#xff1b; 2&#xff09;从节点端&#xff1a;每个partition至少需要一个isr节点&#xff0…...

解决树莓派 bullseye (11) 系统无法通过 xrdp 远程连接的问题

我手上有一台树莓派 4B&#xff0c;使用官方镜像烧录器烧录老版本操作系统 buster (10) 时可以正常通过 Windows 远程桌面连接上&#xff0c;但换成最新的 bullseye (11) 系统后却无法正常连接远程桌面。 问题复现&#xff1a; 使用官方镜像烧录器烧录&#xff0c;配置用户名为…...

微信公众号历史作品定向采集

最近有遇到微信公众号历史作品采集的需求,这里做一下记录, 登录自己注册好的的微信公众号后台进入创作界面,点击右上角的引用: 弹出如下界面: 选择查找公众号文章,输入要查找的公众号: 回车: 同时就可以打开F12开始抓包,选择公众号点击进入: appmsg?action=li…...

Vue学习笔记(3)

3.1 计算属性和监视属性 3.1.1 计算属性 计算属性是一种计算值的方式&#xff0c;可以根据其他属性的值来动态地计算新的属性值。计算属性可以缓存计算结果&#xff0c;当依赖的属性发生改变时&#xff0c;才会重新计算。在Vue中&#xff0c;可以使用computed选项来定义计算属…...

Marshmallow 库

文章目录Marshmallow 库介绍使用序列化反序列化参数介绍schema参数fields 参数钩子函数内置验证器Meta 属性Marshmallow 库 介绍 marshmallow是一个用来将复杂的orm对象与python原生数据类型之间相互转换的库&#xff0c;简而言之&#xff0c;就是实现object -> dict&#…...

【BN层的作用】论文阅读 | How Does Batch Normalization Help Optimization?

前言&#xff1a;15年Google提出Batch Normalization&#xff0c;成为深度学习最成功的设计之一&#xff0c;18年MIT团队将原论文中提出的BN层的作用进行了一一反驳&#xff0c;重新揭示BN层的意义 2015年Google团队论文&#xff1a;【here】 2018年MIT团队论文&#xff1a;【h…...

re.sub()用法的详细介绍

一、前言 在字符串数据处理的过程中&#xff0c;正则表达式是我们经常使用到的&#xff0c;python中使用的则是re模块。下面会通过实际案例介绍 re.sub() 的详细用法&#xff0c;该函数主要用于替换字符串中的匹配项。 二、函数原型 首先从源代码来看一下该函数原型&#xf…...

【Python数据挖掘入门】2.2文本分析-中文分词(jieba库cut方法/自定义词典load_userdict/语料库分词)

中文分词就是将一个汉字序列切分成一个一个单独的词。例如&#xff1a; 另外还有停用词的概念&#xff0c;停用词是指在数据处理时&#xff0c;需要过滤掉的某些字或词。 一、jieba库 安装过程见&#xff1a;https://blog.csdn.net/momomuabc/article/details/128198306 ji…...

Meta利用视觉信息来优化3D音频模型,未来将用于AR/VR

我们知道&#xff0c;Meta为了给AR眼镜打造智能助手&#xff0c;专门开发了第一人称视觉模型和数据集。与此同时&#xff0c;该公司也在探索一种将视觉和语音融合的AI感知方案。相比于单纯的语音助手&#xff0c;同时结合视觉和声音数据来感知环境&#xff0c;可进一步增强智能…...

openlayers加载离线地图并实现深色地图

问题背景 我们自己一直使用的openlayergeoserver自己发布的地图&#xff0c;使用的是矢量地图。但是由于政府地图大都使用为天地图&#xff0c;所以需要将geoserver的矢量地图更改为天地图&#xff0c;并且依旧是搭配openlayers来使用。 解决步骤 一&#xff1a;加载离线地图&a…...

socket,tcp,http三者之间的区别和原理

目录 一、OSI模型也称七层网络模型 1、TCP/IP连接 1.1三次握手与四次挥手的简单理解&#xff1a;&#xff08;面试重点&#xff09; 1.2面试考题&#xff1a;如果已经建立了连接&#xff0c;但是客户端突然出现故障了怎么办&#xff1f; 1.3 socket、tcp、http三者之间有什…...

红日(vulnstack)1 内网渗透ATTCK实战

环境准备 靶机链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;sx22 攻击机系统&#xff1a;kali linux 2022.03 网络配置&#xff1a; win7配置&#xff1a; kali配置&#xff1a; kali 192.168.1.108 192.168.111.129 桥接一块&#xff0c;自定义网卡4 win7 1…...

ik 分词器怎么调用缓存的词库

IK 分词器是一个基于 Java 实现的中文分词器&#xff0c;它支持在分词时调用缓存的词库。 要使用 IK 分词器调用缓存的词库&#xff0c;你需要完成以下步骤&#xff1a; 创建 IK 分词器实例 首先&#xff0c;你需要创建一个 IK 分词器的实例。可以通过以下代码创建一个 IK 分…...

ROS1/2机器人操作系统与时间Time的不解之缘

时间对于机器人操作系统非常重要。所有机器人类的编程中所涉及的变量如果需要在网络中传输都需要这个数据结构的时间戳。宏观上&#xff0c;ROS1、ROS2各版本都有官方支持的时间节点。ROS时钟--支持时间倒计时小工具效果如下&#xff1a;如果要部署机器人操作系统&#xff0c;R…...

华为OD机试真题2022(JAVA)

华为机试题库已换 →→→ 华为OD机试2023&#xff08;JAVA&#xff09; 以下题目为旧版题库&#xff0c;供大家课外消遣 基础题&#xff1a; 序号题目分值1查找众数及中位数1002出错的或电路1003连续字母长度1004分班1005计算面积1006最远足迹1007判断一组不等式是否满足约束…...

【3】MyBatis+Spring+SpringMVC+SSM整合一套通关

三、SpringMVC 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体…...

20道前端高频面试题(附答案)

ES6新特性 1.ES6引入来严格模式变量必须声明后在使用函数的参数不能有同名属性, 否则报错不能使用with语句 (说实话我基本没用过)不能对只读属性赋值, 否则报错不能使用前缀0表示八进制数,否则报错 (说实话我基本没用过)不能删除不可删除的数据, 否则报错不能删除变量delete p…...

android EditText设置后缀

有两种实现方案。 方案一&#xff1a;是自己写一个TextWatcher。 方案二&#xff1a;是重写TextView的getOffsetForPosition方法&#xff0c;返回一个计算好的offset。 我在工作时&#xff0c;使用的是方案一。在离职之后&#xff0c;我还是对这个问题耿耿于怀&#xff0c;所以…...

prometheus+cadvisor监控docker

官方解释 cAdvisor&#xff08;ContainerAdvisor&#xff09;为容器用户提供了对其运行容器的资源使用和性能特性的了解。它是一个正在运行的守护程序&#xff0c;用于收集、聚合、处理和导出有关正在运行的容器的信息。具体来说&#xff0c;它为每个容器保存资源隔离参数、历史…...

正演(1): 二维声波正演模拟程序(中心差分)Python实现

目录 1、原理&#xff1a; 1&#xff09;二维声波波动方程: ​编辑 2&#xff09;收敛条件&#xff08;不是很明白&#xff09; 3&#xff09;雷克子波 4&#xff09;二维空间衰减函数 5&#xff09;边界吸收条件 (不是很明白。。) 2、编程实现 1&#xff09;参数设置&…...

珠海数据智能监控器+SaaS平台 轻松实现SMT生产管控

数据智能监控器 兼容市面上99%的SMT设备 直接读取设备生产数据与状态&#xff0c;如&#xff1a;计划产出、实际产出、累计产出、停机、节拍、线利用率、直通率、停产时间、工单状态、OEE…… 产品功能价值 ◎ OEE不达标报警&#xff0c;一手掌握生产效能 ◎ 首检/巡检/成…...

习题22对前面21节的归纳总结

笨方法学python --习题22 Vi---Rum 于 2021-01-12 14:16:10 发布 python 习题22 这节内容主要是归纳总结 ex1.py 第一次学习 1.print&#xff1a;打印 2.# &#xff1a;是注释的意思&#xff0c;井号右边的内容不再执行 3.end"":,在句子结尾加上这个就不会再换行…...

使用Vite快速构建前端React项目

一、Vite简介 Vite是一种面向现代浏览器的一个更轻、更快的前端构建工具,能够显著提升前端开发体验。除了Vite外,前端著名的构建工具还有Webpack和Gulp。目前,Vite已经发布了Vite3,Vite全新的插件架构、丝滑的开发体验,可以和Vue3完美结合。 相比Webpack和Gulp等构建工具…...

人工智能高等数学--人工智能需要的数学知识_微积分_线性代数_概率论_最优化---人工智能工作笔记0024

然后我们看一下人工智能中需要的数学知识 数学知识是重要的,对于理解人工智能底层原理来说很重要,但是工作中 工作中一般都不会涉及的自己写算法之类的,只是面试,或者理解底层原理的时候需要 然后看一下人工智能需要哪些数学知识 这里需要微积分 线性代数 概率论 最优化的知识…...

阿里大数据之路总结

一、数据采集 二、数据同步 2.1、数据同步方式&#xff1a; 数据同步的三种方式&#xff1a;直连方式、数据文件同步、数据库日志解析方式 关系型数据库的结构化数据&#xff1a;MYSQL、Oracle、DB2、SQL Server非关系型数据库的非结构化数据&#xff08;数据库表形式存储&am…...

wordpress更新提示关闭/seo工具包括

文章目录一、简介二、安全加固方案1、隐藏 module 信息2、使用权限控制3、限制网络访问4、启用账户认证5、数据加密传输一、简介 Rsync 是一个通过检查文件的时间戳和大小&#xff0c;来跨计算机系统高效地传输和同步文件的工具。 通常情况下&#xff0c;管理程序在启动 Rsyn…...

兰州网站建设哪家好/网站排名软件有哪些

《Chip Design》杂志上最近的一篇文章指出&#xff0c;便携式和无线系统有了巨大的增长&#xff0c;并且与软件的关联越来越大&#xff0c;这让嵌入式系统面临很大的挑战。我们需要对质量问题给予特别的关注&#xff0c;特别是在对安全性要求较高的系统中。正如杂志所做结论所说…...

二级域名网站可以做关键词优化吗/今日广东头条新闻

Emacs v25.1 在win7 卡顿得厉害&#xff0c;滚动条拖动一下&#xff0c;就卡半天没反应&#xff0c;就像中了病毒一样。 解决&#xff1a; 打开菜单Options->Set Default Font&#xff0c;将字体改为宋体。 然后再回到Options菜单&#xff0c;点Save Options。这一步可千…...

猎头公司网站模板/晚上国网app

插入表格/列表/图片 新建桌面应用程序testRichText&#xff0c;基类QMainWindow,勾选创建界面文件&#xff0c;其他选择默认。编辑mainwindow.cpp构造函数 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui {class MainW…...

佛山网站建设哪家便宜/怎样在百度打广告

前言 想要成為一名優秀的Android開發&#xff0c;你需要一份完備的 知識體系&#xff0c;在這裏&#xff0c;讓我們一起成長為自己所想的那樣。 金九银十是大家的換工作潮&#xff0c;在這波浪潮裡沉浮的我經歷過快一個月的面試後&#xff0c;決定把這些遇到的問題記下來 加…...

哪个网站做代购/百度怎么优化关键词排名

Spring核心系列之AOP(一) Hello&#xff0c;大家好&#xff0c;今天来给大家讲一讲Spring中的AOP&#xff0c;面向切面编程&#xff0c;它在Spring的整个体系中占有着重要地位。本文还是以实践为主&#xff0c;注解切入注入&#xff0c;OK&#xff0c;文章结构: AspectJ 详解Sp…...