Spring企业开发核心框架-下
五、Spring AOP面向切面编程
1、场景设定和问题复现
①准备AOP项目
项目名:Spring-aop-annotation
②声明接口
/*** + - * / 运算的标准接口!*/
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);}
③实现接口
/*** 实现计算接口,单纯添加 + - * / 实现! 掺杂其他功能!*/
public class CalculatorPureImpl implements Calculator { @Overridepublic int add(int i, int j) { int result = i + j; return result;} @Overridepublic int sub(int i, int j) { int result = i - j; return result;} @Overridepublic int mul(int i, int j) { int result = i * j; return result;} @Overridepublic int div(int i, int j) { int result = i / j; return result;}
}
④声明带日志接口实现
新需求:需要在每一个方法中,添加控制台输出,输出参数和输出计算后的返回值!
/*** 在每个方法中,输出传入的参数和计算后的返回结果!*/
public class CalculatorLogImpl implements Calculator { @Overridepublic int add(int i, int j) { System.out.println("参数是:" + i + "," + j);int result = i + j;System.out.println("方法内部 result = " + result); return result;} @Overridepublic int sub(int i, int j) { System.out.println("参数是:" + i + "," + j); int result = i - j; System.out.println("方法内部 result = " + result);return result;} @Overridepublic int mul(int i, int j) { System.out.println("参数是:" + i + "," + j); int result = i * j; System.out.println("方法内部 result = " + result); return result;} @Overridepublic int div(int i, int j) { System.out.println("参数是:" + i + "," + j); int result = i / j; System.out.println("方法内部 result = " + result); return result;}
}
⑤代码问题分析
1)代码缺陷
- 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力
- 附加功能代码重复,分散在各个业务功能方法中,冗余,且不方便统一维护!
2)解决问题
- 核心就是:解耦。我们需要把附加功能从业务功能代码中抽取出来。将重复的代码统一提取,并且【动态插入】到每个业务方法!
3)技术困难
- 解决问题的困难:提取重复附加功能代码到一个类中,可以实现但是如何将代码插入到各个方法中?我们不会,我们需要引用新技术!!!
2、解决技术代理模式
① 代理模式
23种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直视对目标方法进行调用,而是通过代理类间调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。
代理场景:

- 代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。(中介)
- 动词:指做代理这个动作,或这项工作
- 名词:扮演代理这个角色的类、对象、方法
- 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。代理在开发中实现的方式具体有两种:静态代理,动态代理。
② 静态代理
主动创建代理类:
public class CalculatorStaticProxy implements Calculator { // 将被代理的目标对象声明为成员变量private Calculator target; public CalculatorStaticProxy(Calculator target) {this.target = target;} @Overridepublic int add(int i, int j) { // 附加功能由代理类中的代理方法来实现System.out.println("参数是:" + i + "," + j); // 通过目标对象来实现核心业务逻辑int addResult = target.add(i, j); System.out.println("方法内部 result = " + result); return addResult;}……
静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将其他地方也需要附加日志,那还得再声明更多个静态代理类,那就生产了大量重复代码,日志功能还是分散的,没有统一管理。
③ 动态代理
- JDK动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口!它会根据目标类的接口动态生成一个代理对象!代理对象和目标对象有相同的接口!(拜把子)
- cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口!(认干爹)
代理工程:基于jdk代理技术,生成代理对象
public class ProxyFactory<T> {//目标对象。具体什么类型由调用者指定private T target;public ProxyFactory(T target) {this.target = target;}public T getProxy(){//1、获取目标对象的类加载器ClassLoader classLoader = target.getClass().getClassLoader();//2、获取目标对象所实现的所有对象Class<?>[] interfaces = target.getClass().getInterfaces();//1、JDK动态代理方式:T o = (T)Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler());return o;}public class MyInvocationHandler implements InvocationHandler{@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//反射角度:method是目标方法,args是目标方法执行时所需要的参数。System.out.println("日志功能,"+method.getName()+"方法执行了,参数为:"+ Arrays.toString(args));//核心:目标方法Object result = method.invoke(target, args);System.out.println("日志功能,"+method.getName()+"方法执行结束,结果为:"+ result);return result;}}
}
④ 代理总结
代理方式可以解决附加功能代码干扰核心代码和不方便统一维护的问题!
它主要是将附加功能代码提取到代理中执行,不干扰目标核心代码。但是我们也发现,无论使用静态代理和动态代理,程序员的工作都比较繁琐,需要自己编写代理工厂等。但是,提前剧透,我们在实际开发中,不需要编写代理代码,我们可以使用SpringAOP框架,它会简化代理的实现!
3、面向切面编程思维(AOP)
1)面向切面编程思想AOP
AOP:Aspect Oriented Programming 面向切面编程
AOP可以说是OOP的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都如此,这种散布在各处的无关的代码被称为横切,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
相关文章:
Spring企业开发核心框架-下
五、Spring AOP面向切面编程 1、场景设定和问题复现 ①准备AOP项目 项目名:Spring-aop-annotation ②声明接口 /*** - * / 运算的标准接口!*/ public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, in…...
X射线底片焊缝缺陷检测
实现四种焊缝缺陷的检测和分割处理。...
直播的js代码debug解析找到protobuf消息的定义
我们都知道直播的弹幕消息是通过websocket发送的,而且是通过protobuf传输的,那么这里面传输了哪些内容,这个proto文件又要怎么定义?每个消息叫什么,消息里面又包含有哪些字段,每个字段又是什么类型…...
详细学习es6扩展运算符
ES6中的扩展运算符(Spread Operator)是一种非常方便的语法,主要用于将可迭代对象(比如数组、字符串等)展开成多个参数。以下是关于ES6扩展运算符的详细内容: 用法: 在数组字面量中展开数组&am…...
HEC-HMS水文模型教程
原文链接:HEC-HMS水文模型教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247607904&idx5&sn1a210328a3fc8f941b433674d8fe2c85&chksmfa826787cdf5ee91d01b6981ebd89deac3e350d747d0fec45ce2ef75d7cb8009341c6f55114d&token90645021…...
Spring Cloud LoadBalancer基础入门与应用实践
官网地址:https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html 【1】概述 Spring Cloud LoadBalancer是由SpringCloud官方提供的一个开源的、简单易用的客户端负载均衡器,它包含在SpringCloud-commons中用…...
layui在表格中嵌入上传按钮,并修改上传进度条
当需要在表格中添加上传文件按钮,并不需要弹出填写表单的框的时候,需要在layui中,用按钮触发文件选择 有一点需要说明的是,layui定义table并不是在定义的标签中渲染,而是在紧接着的标签中渲染,所以要获取实…...
14-10 AIGC 项目生命周期——第一阶段
生成式 AI 项目生命周期的整个过程类似于从范围、选择、调整和对齐/协调模型以及应用程序集成开始的顺序依赖过程。流程表明每个步骤都建立在前一步的基础上。有必要了解每个阶段对于项目的成功都至关重要。 下面的流程图重点介绍了生成式 AI 项目生命周期的第一阶段 1 — “范…...
经典小游戏(一)C实现——三子棋
switch(input){case 1:printf("三子棋\n");//这里先测试是否会执行成功break;case 0:printf("退出游戏\n");break;default :printf("选择错误,请重新选择!\n");break;}}while(input);//直到输入的结果为假,循环才会结束} …...
如何利用AI生成可视化图表(统计图、流程图、思维导图……)免代码一键绘制图表
由于目前的AI生成图表工具存在以下几个方面的问题: 大多AI图表平台是纯英文,对国内用户来说不够友好;部分平台在生成图表前仍需选择图表类型、配置项,操作繁琐;他们仍需一份规整的数据表格,需要人为对数据…...
Firefox 编译指南2024 Windows10-使用Git 管理您的Firefox(五)
1. 引言 在现代软件开发中,版本控制系统(VCS)是不可或缺的工具,它不仅帮助开发者有效管理代码的变化,还支持团队协作与项目管理。Mercurial 是一个高效且易用的分布式版本控制系统,其设计目标是简洁、快速…...
ubuntu 18 虚拟机安装(1)
ubuntu 18 虚拟机安装 ubuntu 18.04.6 Ubuntu 18.04.6 LTS (Bionic Beaver) https://releases.ubuntu.com/bionic/ 参考: 设置固定IP地址 https://blog.csdn.net/wowocpp/article/details/126160428 https://www.jianshu.com/p/1d133c0dec9d ubuntu-18.04.6-l…...
Github 上 Star 数最多的大模型应用基础服务 Dify 深度解读(一)
背景介绍 接触过大模型应用开发的研发同学应该都或多或少地听过 Dify 这个大模型应用基础服务,这个项目自从 2023 年上线以来,截止目前(2024-6)已经获得了 35k 多的 star,是目前大模型应用基础服务中最热门的项目之一…...
XStream导出xml文件
最终效果 pom依赖 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.11.1</version></dependency>代码 XStreamUtil 这个直接复制即可 import com.thoughtworks.xst…...
陪诊小程序搭建:构建便捷医疗陪诊服务的创新实践
在当今快节奏的社会,医疗服务与人们的生活息息相关。然而,在医疗体系中,患者往往面临着信息不对称、流程繁琐、陪伴需求得不到满足等问题。为了解决这些问题,我们提出了一种创新的解决方案——陪诊小程序,旨在为患者提…...
0139__TCP协议
全网最详细TCP参数讲解,再也不用担心没有面试机会了_tcp的参数-CSDN博客 TCP协议详解-腾讯云开发者社区-腾讯云 TCP-各种参数 - 简书...
家政小程序的开发,带动市场快速发展,提高家政服务质量
当下生活水平逐渐提高,也增加了年轻人的工作压力,同时老龄化也在日益增加,使得大众对家政的需求日益提高,能力、服务质量高的家政人员能够有效提高大众的生活幸福指数。 但是,传统的家政服务模式存在着效率低、用户与…...
JavaScript高级程序设计(第四版)--学习记录之对象、类与面向对象编程(下)
类 ES6新引入class关键字具有正式定义类的能力。 类定义:类声明和类表达式。 // 类声明 class Person {} // 类表达式 const Animal class {}; 类定义与函数定义的不同: 1:函数声明可以提升,类定义不能 2:函数受函数…...
PDF 生成(5)— 内容页支持由多页面组成
当学习成为了习惯,知识也就变成了常识。 感谢各位的 关注、点赞、收藏和评论。 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/blog,欢迎 Watch 和 Star。 回顾 在本篇开始…...
day 51 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离
115. 不同的子序列 给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 7 取模。 示例 1: 输入:s "rabbbit", t "rabbit" 输出:3 解释: 如下所示,…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
