Spring-aop特点,专业术语及案例演示
一.aop简介
AOP(Aspect-Oriented Programming)是Spring框架的一个重要特性,它通过将横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,以模块化的方式在整个应用程序中重复使用。以下是关于AOP的简介及其特点:
简介:
- AOP是一种编程范式,它通过将横切关注点切割出来,将其模块化,并将其应用于多个类和模块,以提高代码的重用性和可维护性。
- 横切关注点是指与核心业务逻辑无关但存在于多个类或模块中的非功能性需求,例如日志记录、性能监控、事务管理等。
特点:
- 模块化:AOP允许将横切关注点从核心业务逻辑中提取出来,形成独立的切面(Aspect),使得关注点的逻辑可以独立于各个模块。
- 解耦:AOP通过解耦横切关注点与核心业务逻辑,使得它们可以独立演化和变化,提高了模块之间的松耦合程度。
- 重用性:AOP允许将切面应用于多个类和模块,从而实现了关注点的重用,避免了代码的重复编写。
- 可维护性:将横切关注点抽象为切面后,使得代码结构更清晰,易于理解和维护。
- 动态性:AOP可以在运行时动态地将切面应用到目标对象上,而不需要修改目标对象的源代码,增强了系统的灵活性和可扩展性。
- 多样性:Spring框架支持不同类型的切面编程,包括基于代理的AOP和基于字节码增强的AOP。这样可以选择最适合应用程序需求的AOP实现方式。
在Spring框架中,AOP的实现采用了代理模式和动态代理技术。Spring提供了多种AOP的实现方式,包括基于XML配置的AOP、基于注解的AOP和基于纯Java配置的AOP(JavaConfig)等,开发者可以根据具体需求选择适合的方式来配置和使用AOP。
二.aop中的专业术语
切面(Aspect):切面是一个模块化单元,用于解耦和封装横切关注点的逻辑。切面由切点和通知组成,它定义了何时在何处应用通知。
切点(Pointcut):切点定义了在应用程序中哪些位置应该应用通知。它通过表达式或模式匹配规则来指定需要被拦截的连接点(Join Point)。
连接点(Join Point):连接点是在应用程序执行过程中可以插入切面的特定点。例如方法执行、异常抛出、字段访问等都可以是连接点。
通知(Advice):通知是在切面的特定连接点上执行的动作。在Spring AOP中,有以下几种通知类型:
- 前置通知(Before Advice):在连接点之前执行的通知。
- 后置通知(After Advice):在连接点之后执行的通知。
- 返回通知(After Returning Advice):在连接点成功完成后执行的通知。
- 异常通知(After Throwing Advice):在连接点发生异常时执行的通知。
- 环绕通知(Around Advice):在连接点前后都执行的通知,可以控制方法的执行。
引入(Introduction):引入是一种给现有类添加新方法或属性的方式。它允许在不修改原始类代码的情况下,向类添加新功能。
织入(Weaving):织入是将切面应用到目标对象上以创建新的代理对象的过程。在Spring AOP中,织入可以在编译时、类加载时或运行时进行。
目标对象(Target Object):目标对象是被切面通知的真实对象。它是应用程序中具体业务逻辑的实现。
异常处理(Exception Handling):异常处理是在连接点发生异常时,切面执行的特定动作。它可以捕获和处理异常,提供错误处理或回滚事务等功能。
三.案例演示
1.前置通知
1.1 先准备接口
package com.YU.aop.biz;public interface IBookBiz {// 购书public boolean buy(String userName, String bookName, Double price);// 发表书评public void comment(String userName, String comments); }
1.2然后再准备好实现类
package com.YU.aop.biz.impl;import com.YU.aop.biz.IBookBiz; import com.YU.aop.exception.PriceException;public class BookBizImpl implements IBookBiz {public BookBizImpl() {super();}public boolean buy(String userName, String bookName, Double price) {// 通过控制台的输出方式模拟购书if (null == price || price <= 0) {throw new PriceException("book price exception");}System.out.println(userName + " buy " + bookName + ", spend " + price);return true;}public void comment(String userName, String comments) {// 通过控制台的输出方式模拟发表书评System.out.println(userName + " say:" + comments);}}
1.3对我们的目标对象进行JavaBean配置
<!--目标对象--><bean class="com.YU.aop.biz.impl.BookBizImpl" id="bookBiz"></bean>
1.4 编写前置系统日志通知
package com.YU.aop.advice;import java.lang.reflect.Method; import java.util.Arrays;import org.springframework.aop.MethodBeforeAdvice;/*** 买书、评论前加系统日志* @author YU**/ public class MyMethodBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { // 在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去String target = arg2.getClass().getName();String methodName = arg0.getName();String args = Arrays.toString(arg1);System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+")被调用了");}}
1.5配置系统通知XML中的JavaBean
<!--通知--><bean class="com.YU.aop.advice.MyMethodBeforeAdvice" id="myMethodBeforeAdvice"></bean>
1.6 配置代理XML中的JavaBean
<!-- 代理--><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy"><!-- 配置目标对象 --><property name="target" ref="bookBiz"></property><!-- 配置代理接口,目标对象的接口 --><property name="proxyInterfaces"><value>com.YU.aop.biz.IBookBiz</value></property><property name="interceptorNames"><list><value>myMethodBeforeAdvice</value></list></property></bean>
1.7 测试代码开始测试
package com.YU.aop.test;import com.YU.aop.biz.IBookBiz; import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author YU* @create 2023-08-17 15:14*/ public class Test1 {public static void main(String[] args) {//建模ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml"); // IBookBiz bookBiz = (IBookBiz) context.getBean("bookBiz");IBookBiz bookBiz = (IBookBiz) context.getBean("bookProxy");bookBiz.buy("死仔","我的26岁女房客",18.8d);bookBiz.comment("死仔","真好看");} }
测试结果:
由测试结果可得知,不仅获取到了我们的参数,同时根据方法获取到了我们的系统日志,也就是前置通知
2. 后置通知
2.1 先准备好后置通知的系统日志
package com.zking.aop.advice;import java.lang.reflect.Method; import java.util.Arrays;import org.springframework.aop.AfterReturningAdvice;/*** 买书返利* @author Administrator**/ public class MyAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {String target = arg3.getClass().getName();String methodName = arg1.getName();String args = Arrays.toString(arg2);System.out.println("【后置通知:买书返利】:"+target+"."+methodName+"("+args+")被调用了,"+"该方法被调用后的返回值为:"+arg0);}}
2.2 配置后置系统通知的XML的JavaBean
<!--后置通知--><bean class="com.YU.aop.advice.MyAfterReturningAdvice" id="myAfterReturningAdvice"></bean>
并在前面已经配置好的代理接口中添加一个value值
2.3 测试结果
由测试结果我们可以得知,后置通知永远都在方法执行后才会显示通知,与前置通知不同的是每次前面的方法调用后都会返回一个参数
3.环绕通知
3.1 环绕通知就是前置通知和后置通知的结合,在实际应用开发中,我们一般不会单独编写前置通知和后置通知,单独使用前置通知或者后置通知时,我们会使用环绕通知,将里面前置(后置)通知的功能注释,以达到单独使用的目的
3.2 环绕通知的系统日志
package com.YU.aop.advice;import java.util.Arrays;import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation;/*** 环绕通知* 包含了前置和后置通知* * @author Administrator**/ public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation arg0) throws Throwable {String target = arg0.getThis().getClass().getName();String methodName = arg0.getMethod().getName();String args = Arrays.toString(arg0.getArguments());System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了"); // arg0.proceed()就是目标对象的方法Object proceed = arg0.proceed();System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed);return proceed;}}
3.3 配置环绕通知的XML的JavaBean与前置通知和后置通知一致
3.4 测试结果
由测试结果得知,环绕通知就是前置通知和后置通知的结合,优点就是不需要再多次去进行配置及编码,所以就像我们前面所说在实际开发应用中我们一般都会选择使用环绕通知
4.异常通知
4.1 异常通知的系统日志和其他系统日志不同的是,方法名为固定的afterThrowing,不能修改
package com.YU.aop.advice;import org.springframework.aop.ThrowsAdvice;import com.YU.aop.exception.PriceException;/*** 出现异常执行系统提示,然后进行处理。价格异常为例* @author Administrator**/ public class MyThrowsAdvice implements ThrowsAdvice {public void afterThrowing(PriceException ex) {System.out.println("【异常通知】:当价格发生异常,那么执行此处代码块!!!");} }
4.2 在我们正常程序出问题没有去配置异常通知时会出现报错,并且不会执行后面的后置通知,如以下情况
4.3 异常处理配置和前面的配置相同
4.4 当我们配置好异常通知模块时,程序出现异常时会上报日志进行提示
5.过滤通知
5.1 直接在XML中配置JavaBean
<!--过滤通知--><bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpMethodPointcutAdvisor"><property name="advice" ref="myAfterReturningAdvice"></property><property name="pattern" value=".*buy"></property></bean>
将图中指出部分替换成过滤通知
测试结果:
对比框中内容,在调用过buy方法后进行过滤,第二次调用时不再buy方法而是comment方法
四.总结
aop是面向切面编程,普通程序由上而下正常执行,aop的程序执行是先执行到目标对象的目标方法中,如果连接点上由前置通知,则先执行前置通知再执行目标方法,最后如果目标方法有后置通知则最后执行后置通知代码,不管是前置通知,后置通知,环绕通知,异常通知,过滤通知,代码都是非业务核心代码,如日志、事务的管理(开启、提交、回滚)
相关文章:

Spring-aop特点,专业术语及案例演示
一.aop简介 AOP(Aspect-Oriented Programming)是Spring框架的一个重要特性,它通过将横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,以模块化的方式在整个应用程序中重复使用。以下是关于AOP…...

探秘Java的Map集合:键值映射的奇妙世界
文章目录 1. 单列集合 vs. 双列集合2. Map接口:键与值的契约3. 深入探索HashMap3.1 特性与构造方法3.2 常用方法3.3 遍历HashMap 4. 美妙的LinkedHashMap 在Java编程中,集合是不可或缺的重要部分,它为我们提供了各种数据结构和算法的实现。其…...

git权限问题解决方法Access denied fatal: Authentication failed
文章目录 遇到Access denied 的权限问题解决方法1、git的密码修改过,但是本地没更新。2、确定问题,然后增加配置① 查询用户信息②如果名称和email不对,设置名称:③ 检查ssh-add是否链接正常④ 设置不要每次都输入用户名密码 3、配…...

Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC)
Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC) 文章目录 Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC)1. 理论基础1.1 Maximum Entropy Reinforcement Learning, MERL1.2 Soft Policy Evaluation and Soft Policy Improvement in SAC1.3 Tw…...

JavaScript中的this指向,call、apply、bind的简单实现
JavaScript中的this this是JavaScript中一个特殊关键字,用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的,是再函数被调用时根据调用场景动态确定的,主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时…...

Linux学习之基本指令一
在学习Linux下的基本指令之前首先大家要知道Linux下一切皆目录,我们的操作基本上也都是对目录的操作,这里我们可以联想我们是如何在windows上是如何操作的,只是形式上不同,类比学习更容易理解。 目录 01.ls指令 02. pwd命令 0…...

appium默认60秒关闭应用的问题
问题:appium默认启动一个应用的session过期时间是60秒到时间会自动停了刚启动的应用,工作台打印:info: [debug] We shut down because no new commands came in的日志 分析:--command-timeout 60 The default command timeout fo…...

Docker 容器内无法使用vim命令 解决方法
目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 进入Docker容器后 无法使用vim编辑器,出现如下问题:bash: vim: command not found 如图所示: 想着通过apt-get 安装vim,出现如下问题: root@b9f0fd330d5b:/# apt-get install vim Reading package lists... Done B…...

Django的简介安装与配置及两大设计模式
一.Djang的介绍 1.Django是什么 Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。 由于 Python 语言的跨平台性,所以 Django 同样支持 Windows、Linux 和 Mac 系统。 在 Python 语言炽手可热的当下,Django 也迅速的崛起,在…...

Mybatis分页插件——PageHelper
一、定义 PageHelper用在mybatis插件里面,可以自动的为最近的sql语句进行分页查询,提供分页的页码size和每页数量num,在查询过程中hi自动的拼接limit关键字,不用再改写sql语句了 在PageHelper.startPage(); 在启动查询…...

k8s认证详解 k8s证书详解 2023推荐
推荐阅读 https://www.yii666.com/blog/478731.html?actiononAll 在 Kube-apiserver 中提供了很多认证方式,其中最常用的就是 TLS 认证,当然也有 BootstrapToken,BasicAuth 认证等,只要有一个认证通过,那么 Kube-api…...

php初解
php是什么? PHP,全称 Hypertext Preprocessor ,中文翻译“超文本预处理器”。 PHP是一种被广泛应用的开源通用脚本语言,尤其适用于 Web 开发。 拥有快速,灵活,实用的特点,PHP能做任何事…...

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解
文章目录 前言一、回调函数是什么二、回调函数的使用1.使用标准库中的qsort函数2.利用qsort函数对结构体数组进行排序 三、实现qsort函数总结 先记录一下访问量突破2000啦,谢谢大家支持!!! 这里是上期指针进阶链接,方便…...

PHP手术麻醉系统源码,自动生成麻醉和护理医疗文书
一套手术麻醉系统源码,可二次开发 手术室麻醉临床信息系统(AIMS)是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期,对病人进行全程跟踪与信息管理,自动集成病人HIS、LIS、RIS、PACS信息࿰…...

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】
通过cpolar分享本地电脑上有趣的照片:发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片:发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…...

iPhone删除的照片能恢复吗?不小心误删了照片怎么找回?
iPhone最近删除清空了照片还能恢复吗?大家都知道,照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活,也留住了我们的美好瞬间,具有极其重要的纪念价值。 照片不小心误删是一件非常难受的事,那么iP…...

LeetCode--HOT100题(32)
目录 题目描述:138. 复制带随机指针的链表(中等)题目接口解题思路代码 PS: 题目描述:138. 复制带随机指针的链表(中等) 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random &…...

SAP MM学习笔记24-以评估收货(评价)和非评估收货(非评价)
SAP 中 有评价入库(评估收货)和非评价入库(非评估收货)两种入库方式。 一般来说在库品目会采用评价入库,而消费品目,会采用非评价入库。 其实评价入库,非评价入库对外都无所谓的,人…...

Hadoop的DataNode无法启动的解决方案
Hadoop重启一次,里面的数据需要重新导入,发现无法导入数据,查看jps发现是DataNode没有启动,重新启动发现也无法启动,原因是前面重新启动NameNode,里面的文件格式化一次,DataNode的文件不一致&am…...

re中的match和search有什么区别?
问题:请说明以下re模块中的match和search有什么区别? re.match()与re.search()的区别 re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,结果返回None,而re.search()匹配整个字符串,直到找到一个匹配 re.search() re.search()扫描整个字符串并…...

《内网穿透》无需公网IP,公网SSH远程访问家中的树莓派
文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…...

.net连接mysql,提示找不到请求的 .Net Framework Data Provider。可能没有安装
开发完成的.net程序需要连接mysql数据库,在个人电脑上运行没问题,别人运行时提示“提示找不到请求的 .Net Framework Data Provider。可能没有安装”。经过查询,安装Connector/NET 8.1.0,下载地址如下所示: https://d…...
销售自动化管理软件是什么,销售自动化管理软件有什么优势
阅读本文您可以了解:1、销售自动化管理软件是什么;2、销售自动化管理软件的优势 一、销售自动化管理软件是什么 销售自动化管理软件是一种用于帮助企业有效管理销售流程和客户关系的工具。它集成了各种功能和工具,以简化和自动化销售团队的任…...

MySQL 函数
mysql 函数语法 create function 函数名(参数名 参数类型,。。。) returns type —返回值类型 ----returns 有个 s [characteristics…] begin 函数体 ### 函数体中肯定有 return 语句 end 参数列表 指定参数为 IN | out | INOUT 只对存储过程…...

爬虫逆向实战(六)--猿人学第四题
一、数据接口分析 主页地址:猿人学第四题 1、抓包 通过抓包可以发现数据接口是api/match/4 2、判断是否有加密参数 请求参数是否加密? 无请求头是否加密? 无响应是否加密? 响应数据无加密,但是返回的却是html代码…...

【大数据Hive】hive 事务表使用详解
目录 一、前言 二、Hive事务背景知识 hive事务实现原理 hive事务原理之 —— delta文件夹命名格式 _orc_acid_version 说明 bucket_00000 合并器(Compactor) 二、Hive事务使用限制 参数设置 客户端参数设置 客户端参数设置 三、Hive事务使用操作演示 操作步骤 客…...

网络层协议
网络层协议 IP协议基本概念协议头格式网段划分特殊的IP地址IP地址的数量限制私有IP地址和公网IP地址路由IP协议头格式后续 在复杂的网络环境中确定一个合适的路径 IP协议 承接上文,TCP协议并不会直接将数据传递给对方,而是交付给下一层协议,…...

JWT(JSON Web Token )令牌
1、介绍 jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在通信双方安全的进行信息传输了。 2、jwt组成 第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256…...

leetcode 力扣刷题 滑动窗口 部分题解(记录)
力扣刷题 滑动窗口相关的部分题解 209. 长度最小的子数组904. 水果成篮76. 最小覆盖子串 209. 长度最小的子数组 leetcode题目链接 209.长度最小的子数组 题目内容是这样的:给定一个含有 n个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的…...

Intellij IDEA SBT依赖分析插件
可分析模块和传递依赖 安装完插件后,由于IDEA BUG,会出现两个分析按钮,一个是gradle的,一般是后者是新安装的sbt。 选择需要分析的模块 只需要在project/plugins.sbt中添加代码,启动官方分析插件addDependencyTreeP…...