【推荐】深入浅出学习Spring框架【中】

目录
1.AOP是什么?
2.案列:
3.spring的aop的专业术语
4.代码模拟
4.1 前置通知
3.2.后置通知
3.3.环绕通知
3.4.异常通知
3.5.过滤通知
1.AOP是什么?
- 面向切面编程(Aspect-Oriented Programming)是一种编程范式,它的主要目的是通过预编译和运行期动态代理实现程序功能的横切(cross-cutting)特性,如日志记录、性能统计、事务监控等。它可以帮助开发者将这些原本分散在各个方法或类中的业务逻辑抽象出来,提高代码复用性,降低耦合度
- 面向切面编程的核心思想是将程序分为两个部分:切入点和切面。切入点(entry point)是程序执行过程中需要被拦截的代码段,而切面(weaving)则是实现横切功能的代码段。在运行时,通过动态代理技术,将切入点的代码交由切面织入,实现横切的效果
- 面向切面编程是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只是修改这个行为即可
- AOP通过提供另一种思考程序结构的方式来补充了面向对象编程(OOP)。OOP中模块化的基本单元是类(class),而AOP中模块化的基本单元是切面(aspect)。可以这么理解,OOP是解决了纵向的代码复用问题,AOP是解决了横向的代码复用问题.
2.案列:
场景模拟:这里我模拟的场景为线上书城系统
首先进行一个没有使用Aop的模拟代码展示:
实体类:Book:其中是书籍的属性,行为等 Dao类:BookDao:其中是有关于书籍操作的代码 业务逻辑层:BookBiz:...,BookBizImpl:... Web层:new 对象//增加 public int add(Book book) { b.add() }//修改 public int edit(Book book) { b.edit() }//删除 public int del(Book book) { b.del() }//上架 public int up(Book book) { b.up() }//下架 public int down(Book book) { b.down() }但是很多时候会出现这样的情况:
①用户购买了书籍,却说自己没有收到货物...
②店家发出的货物为空货物,而其却为了牟利,矢口否认...
针对这样的情况,很多时候都没有证据来证明到底是真是假,而在我们成熟的系统中,通常都会添加一个叫做‘日志记录’的东西,它可以用来记录和跟踪系统、应用程序或事件的活动和状态的过程,通俗来说就是使用这个系统的用户的每一步操作都会被记录下来,这样就话就成为一个证据:那成熟的系统应该是怎么样?
实体类:Book:其中是书籍的属性,行为等 Dao类:BookDao:其中是有关于书籍操作的代码 业务逻辑层:BookBiz:...,BookBizImpl:... Web层:new对象//增加 public int add(Book book) { b.add() }//修改 public int edit(Book book) { b.edit() }//删除 public int del(Book book) { b.del() }//上架 public int up(Book book) { datetime=..//操作时的时间 username=...//操作的用户名 args = ...//参数 logBiz.add(datetime,username,args);//将其都添加到日志中去b.up() }//下架 public int down(Book book) { datetime=..//操作时的时间 username=...//操作的用户名 args = ...//参数 logBiz.add(datetime,username,args);//将其都添加到日志中去b.down() }现在是在上架和下架中添加了日志记录,如果要在其他的方法操作中,也添加日志记录的话,那就需要将这一段代码再重复几次,这样就有点麻烦,而且还改变了原有代码的结构,如果需求发生改变,需要对打印的日志内容作出修改,那就必须修改用到了日志记录方法中的所有相关代码,如果是1000个方法呢?每次就需要手动去修改1000个方法中的代码,对项目的维护成本就会很高这也不利于我们的系统维护。然后我们可以用到AOP可以帮助开发者将将原本分散在各个方法或类中的业务逻辑抽象出来,提高代码复用性,降低耦合度,接下怎么提高代码的复用性:
3.spring的aop的专业术语
项目代码但是从上往下依次执行,而现在加入了面向切面的思想,当我们的代码执行到目标对象是,查看连接点是否有前置通知,先执行前置通知,再执行目标方法,如果没有前置通知,那么就直接执行目标方法,最后看连接点上是否有后置通知,如果有,就再执行后置通知,如果没有就执行完了。
- 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
- 目标(Target):被通知(被代理)的对象,就是完成具体的业务逻辑 ,比如书籍的增删改查
- 通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理) ,完成切面编程,非业务核心代码
- 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知), 例子:外科医生+护士只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
- 切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点 , (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序),比如给新增方法添加日志功能
- 适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)
注:目标对象只负责业务逻辑代码
通知对象负责AOP代码,这二个对象都没有AOP的功能,只有代理对象才有。
4.代码模拟
4.1 前置通知
首先,我们先写service接口和实现类进行模拟,在里面写两个方法
package com.sy.aop.biz;public interface IBookBiz {// 购书public boolean buy(String userName, String bookName, Double price);// 发表书评public void comment(String userName, String comments);
}
然后,写实现类,重新这两个方法,并且做了一个价格的判断
package com.sy.aop.biz.impl;import com.sy.aop.biz.IBookBiz;
import com.sy.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);}}
接下来要写上面价格判断的异常
package com.sy.aop.exception;public class PriceException extends RuntimeException {public PriceException() {super();}public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}public PriceException(String message, Throwable cause) {super(message, cause);}public PriceException(String message) {super(message);}public PriceException(Throwable cause) {super(cause);}}
然后,我们先创建一个类,将类名.方法名,携带的参数,作为日志存储到数据库。
package com.sy.aop.advice;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;
import java.util.Arrays;/*** 买书、评论前加系统日志* @author shenyan**/
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+")被调用了");}}
最后,进行一个配置
!--aop-->
<!-- 目标对象 -->
<bean class="com.sy.aop.biz.impl.BookBizImpl" id="bookBiz"></bean><!-- 通知 -->
<bean class="com.sy.aop.advice.MyMethodBeforeAdvice" id="methodBeforeAdvice"></bean><!-- 代理=目标+通知 --><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy"><property name="target" ref="bookBiz"></property><property name="proxyInterfaces"><list><value>com.sy.aop.biz.IBookBiz</value></list></property><property name="interceptorNames"><list><value>myMethodBeforeAdvice</value></list></property></bean>
前台的一个验证:
package com.sy.aop.demo;import com.sy.aop.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author 谌艳* @site www.shenyan.com* @create 2023-08-17 21:13*/
public class demo1 {public static void main (String [] args){ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-context.xml");IBookBiz bookBiz=(IBookBiz) context.getBean("bookBiz");bookBiz.buy("花花","天下掉下一个林妹妹",18.88);bookBiz.comment("嘿嘿","嘿嘿嘿真好看");}
}
结果为展示:

3.2.后置通知
有了前面的铺垫,直接再创建一个后置通知的类,比起前置通知,多了一个参数,就是返回参数
package com.sy.aop.advice;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;
import java.util.Arrays;/*** 买书、评论前加系统日志* @author shenyan**/
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+")被调用了");}}
接着,配置文件即可

然后前台看结果;
package com.sy.aop.demo;import com.sy.aop.biz.IBookBiz;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author 谌艳* @site www.shenyan.com* @create 2023-08-17 21:13*/
public class demo1 {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("花花","天下掉下一个林妹妹",18.88);bookBiz.comment("嘿嘿","嘿嘿嘿真好看");}
}

3.3.环绕通知
结合了前置通知和后置通知,它两个都有所以一般常用这个,
它只有一个参数,但是这一个参数相当于上面前置通知和后置通知的3,4个参数
package com.sy.aop.advice;import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;import java.util.Arrays;/*** 环绕通知* 包含了前置和后置通知* * @author shenyan**/
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.4.异常通知
先建一个类,但是注意,这个异常通知的类,重写的话,方法名字只能是这个,否则报错
然后配置文件:

然后在前台测试:

结果展示:

3.5.过滤通知
过滤通知就是那个适配器,它不需要再建一个类,直接再配置文件里面配置就可以了,需要正则判断,这里举例过滤的是后置通知

结果展示:

今天小编的分享就结束呐,生活总是需要不断去学习新的知识,多想想然后再去实操,持之以恒,经验和思维都会发生转变,我们要保持谦虚学习和自信的态度,各位加油!

相关文章:
【推荐】深入浅出学习Spring框架【中】
目录 1.AOP是什么? 2.案列: 3.spring的aop的专业术语 4.代码模拟 4.1 前置通知 3.2.后置通知 3.3.环绕通知 3.4.异常通知 3.5.过滤通知 1.AOP是什么? 面向切面编程(Aspect-Oriented Programming)是一种编程范式,它的主要…...
使用 HTML、CSS 和 JavaScript 创建多步骤表单
使用 HTML、CSS 和 JavaScript 创建多步骤表单 为了处理又长又复杂的表单,我们需要将它们分成多个步骤。通过一次只在屏幕上显示一些输入,表单会感觉更容易理解,并防止用户感到被大量的表单字段淹没。 在本文中,我将逐步指导如何…...
C语言笔试训练【第九天】
文章目录 👿1、下列程序的输出是( )💎2、二维数组X按行顺序存储,其中每个元素占1个存储单元。若 X[4][4] 的存储地址为 Oxf8b82140 , X[9][9] 的存储地址为 Oxf8b8221c ,则 X[7][7] 的存储地址为( …...
左邻右舍裂差法求和 以及 连续自然数的立方和公式
左邻右舍裂差法求和 1 2 2 3 3 4 4 5 . . . n ( n 1 ) ? 1\times22\times33\times44\times5...n\times(n1)? 12233445...n(n1)? 看成数列 a n n 2 n , ( n ∈ N ) a_nn^2n, (n\in N^) ann2n,(n∈N) 的前 n n n 项和 S n S_n Sn. 原理:将…...
阿里云故障洞察提效 50%,全栈可观测建设有哪些技术要点?
本文根据作者在「TakinTalks 稳定性社区 」公开分享整理而成 #一分钟精华速览# 全栈可观测是一种更全面、更综合和更深入的观测能力,能协助全面了解和监测系统的各个层面和组件,它不仅仅是一个技术上的概念,更多地是技术与业务的结合。在“…...
docker run 命令30个常用参数详解
文章目录 0.前言docker run 命令示例 2.Docker run 多种用法知其然知其所以然1. 基本用法2. 启动交互式容器3. 映射端口4. 挂载文件/目录5. 设置环境变量6. 指定容器名称7. 后台运行容器8. 重启策略9. 其他参数 2. docker run 命令参数详解1. -d:以后台模式…...
[kali]kali linux镜像下载地址
百度网盘地址 链接:https://pan.baidu.com/s/1cxySSyQdLIkox-w_CSka4Q 提取码:cevu 官方下载合集 https://www.kali.org/downloads/(所有版本) 独立链接: 2020.3版本 64位:https://cdimage.kali.org/kali-2020.…...
考研408 | 【操作系统】操作系统的概述
操作系统的概念和功能 导图 操作系统的功能和目标 1.作为系统资源的管理者 2.向上层提供方便易用的服务 3.作为最接近硬件的层次 操作系统的特征 导图 并发 并发VS并行 共享 并发和共享的关系 虚拟 异步 操作系统的发展和分类 导图 1.手工操作 2.批处理阶段--单道批处理系统…...
VM部署CentOS并且设置网络
最近在准备学习k8s,需要部署服务器,所以需要在虚拟机中部署centOS服务,下面是在虚拟机中部署CentOs服务。 其中VM地址在下面 链接:https://pan.baidu.com/s/1hSKr5RfwsabdzNOvHmZ5kw?pwdkys5 提取码:kys5 其中Cent…...
多维时序 | MATLAB实现KOA-CNN-BiGRU-Attention多变量时间序列预测
多维时序 | MATLAB实现KOA-CNN-BiGRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现KOA-CNN-BiGRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现KOA-CNN-BiGRU-Attention多变量时间序列预测,KOA-…...
深入Redis线程模型
目录 1.前言 2.Redis为什么快? 3.Redis 为何选择单线程? 3.1可维护性 3.2并发处理 3.3性能瓶颈 4.Reactor设计模式 5.Redis4.0前 单线程模型 - Event Loop 6.Redis4.0后 多线程异步任务 7.Redis6.0后 多线程网络模型 1.前言 这篇文章我们主要围绕…...
idea cannot download sources 解决方法
问题 点击class文件右上角下载源码失败 解决方案 找到idea terminal 控制台cd 至maven工程执行 mvn dependency:resolve -Dclassifiersources...
CS:GO升级 Linux不再是“法外之地”
在前天的VAC大规模封禁中,有不少Linux平台的作弊玩家也迎来了“迟到”的VAC封禁。 一直以来,Linux就是VAC封禁的法外之地。虽然大部分玩家都使用Windows平台进行游戏。但实际上,使用Linux畅玩CS:GO的玩家也不在少数。 以前V社主要打击W…...
手写spring笔记
手写spring笔记 《Spring 手撸专栏》笔记 IoC部分 Bean初始化和属性注入 Bean的信息封装在BeanDefinition中 /*** 用于记录Bean的相关信息*/ public class BeanDefinition {/*** Bean对象的类型*/private Class beanClass;/*** Bean对象中的属性信息*/private PropertyVal…...
shell的两种属性: 交互(interactive)与登录(login)
1. 背景 在看shell变量的时候引起了兴趣: 局部变量,全局变量,环境变量,shell的配置文件,参考博客: http://c.biancheng.net/view/773.html 2. 交互式与非交互式 参考博客: shell的两个属性:是否交互式(interactive), 是否登录…...
实现简单的element-table的拖拽效果
第一步,先随便创建element表格 <el-table ref"dragTable" :data"tableData" style"width: 100%" border fit highlight-current-row><el-table-column label"日期" width"180"><template slot-sc…...
Web网页浏览器远程访问jupyter notebook服务器【内网穿透】
文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook,它是一个交互式的数据科学和计算环境,支持多种编程语言,如…...
干翻Dubbo系列第十一篇:Dubbo常见协议与通信效率对比
文章目录 文章说明 一:协议 1:什么是协议 2:协议和序列化关系 3:协议组成 (一):头信息 (二):体信息 4:Dubbo3中常见的协议 5:…...
春秋云镜 CVE-2020-17530
春秋云镜 CVE-2020-17530 S2-061 靶标介绍 对CVE-2019-0230的绕过,Struts2官方对CVE-2019-0230的修复方式是加强OGNL表达式沙盒,而CVE-2020-17530绕过了该沙盒。当对标签属性中的原始用户输入进行评估时,强制 OGNL 评估可能会导致远程代码执…...
【java毕业设计】基于Spring Boot+Vue+mysql的论坛管理系统设计与实现(程序源码)-论坛管理系统
基于Spring BootVuemysql的论坛管理系统设计与实现(程序源码毕业论文) 大家好,今天给大家介绍基于Spring BootVuemysql的论坛管理系统设计与实现,本论文只截取部分文章重点,文章末尾附有本毕业设计完整源码及论文的获取…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
