Spring中的适配器模式和策略模式
1. 适配器模式的应用
1.1适配器模式(Adapter Pattern)的原始定义是:将一个类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工作。

1.2 AOP中的适配器模式
在Spring的AOP中,使用Advice(通知)来增强被代理类的功能。Advice的类型有:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice。每种Advice都有对应的拦截器,如MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。

1.3 代码示例
以下示例展示了如何使用适配器模式在Spring AOP中增强一个目标类的功能。
public interface MyService {void doSomething();
}public class MyServiceImpl implements MyService {@Overridepublic void doSomething() {System.out.println("Doing something ...");}
}// 使用Advice(通知)来增强被代理类的功能
public class MyBeforeAdvice implements MethodBeforeAdvice {// 在目标方法执行前进行拦截@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("我变强,也变秃了......");}
}// 自定义适配器对象,将BeforeAdvice对象适配为一个MethodBeforeAdviceInterceptor对象
public class MyBeforeAdviceAdapter extends MethodBeforeAdviceInterceptor {public MyBeforeAdviceAdapter(MethodBeforeAdvice advice) {super(advice);}
}public class Test01 {public static void main(String[] args) {// 创建前置通知对象MyBeforeAdvice advice = new MyBeforeAdvice();// 创建适配器对象,传入通知对象MyBeforeAdviceAdapter adapter = new MyBeforeAdviceAdapter(advice);// 获取目标对象的代理工厂ProxyFactory factory = new ProxyFactory(new MyServiceImpl());// 向代理对象中添加适配器对象factory.addAdvice(adapter);// 获取代理对象MyService proxy = (MyService) factory.getProxy();// 调用代理方法proxy.doSomething();}
}
每个类对应适配器模式中的如下角色:
- Target:
MyServiceImpl类是目标对象,即需要被代理的对象。 - Adapter:
MyBeforeAdviceAdapter类是适配器对象,它将MyBeforeAdvice对象适配为一个MethodBeforeAdviceInterceptor对象,使得MyBeforeAdvice可以被应用到目标对象的代理中。 - Adaptee:
MyBeforeAdvice类是被适配的对象,它定义了一个前置通知方法,在目标方法执行前进行拦截。 - Client:
Test01类是客户端,它通过创建适配器对象并将其添加到目标对象的代理中,实现了在目标方法执行前应用MyBeforeAdvice的前置通知。

2. 策略模式的应用
策略模式是一种行为设计模式,它允许定义一系列算法,将每个算法分别封装起来,并使它们可以相互替换。这种模式使得算法可以在不影响客户端的情况下发生变化。在Spring框架中,策略模式的应用十分广泛,下面是Resource接口及其实现类的示例。
2.1 Resource 接口
Spring框架的资源访问Resource接口提供了强大的资源访问能力。Spring框架本身大量使用了Resource接口来访问底层资源。Resource接口本身没有提供访问任何底层资源的实现逻辑,而是针对不同的底层资源提供了不同的Resource实现类,这些实现类负责不同的资源访问逻辑。
Spring为Resource接口提供了如下实现类:
UrlResource:访问网络资源的实现类。ClassPathResource:访问类加载路径里的资源的实现类。FileSystemResource:访问文件系统里的资源的实现类。ServletContextResource:访问相对于ServletContext路径里的资源的实现类。InputStreamResource:访问输入流资源的实现类。ByteArrayResource:访问字节数组资源的实现类。
这些Resource实现类针对不同的底层资源提供了相应的资源访问逻辑,并提供便捷的包装,以便客户端程序的资源访问。
public class ResourceTest {public static void main(String[] args) throws IOException {// 创建ClassPathResource对象Resource resource = new ClassPathResource("application.properties");// 调用getInputStream()方法读取资源InputStream is = resource.getInputStream();byte[] bytes = new byte[1024];int n;while ((n = is.read(bytes)) != -1) {System.out.println(new String(bytes, 0, n));}is.close();}
}
2.2 DefaultResourceLoader
ResourceLoader接口用于返回Resource对象,其实现可以看作是一个生产Resource的工厂类。当创建Resource对象时,Spring会根据传入的资源路径来选择相应的Resource实现类。这一过程是由Spring中的ResourceLoader接口及其实现类DefaultResourceLoader来完成的。
DefaultResourceLoader中的getResource方法会根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。
public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");// 遍历ProtocolResolver集合,通过ProtocolResolver来解析资源路径for (ProtocolResolver protocolResolver : this.getProtocolResolvers()) {Resource resource = protocolResolver.resolve(location, this);if (resource != null) {return resource;}}// 没有找到对应的ProtocolResolver,使用默认的处理方式if (location.startsWith("/")) {// 以斜杠开头的路径,表示基于ServletContext的相对路径return this.getResourceByPath(location);} else if (location.startsWith("classpath:")) {// 以classpath:开头的路径,表示在classpath下查找资源return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());} else {try {// 尝试将路径解析为URL,如果是文件URL则创建FileUrlResource,否则创建UrlResourceURL url = new URL(location);return (Resource) (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));} catch (MalformedURLException var5) {// 如果路径无法解析为URL,则当做相对路径来处理return this.getResourceByPath(location);}}
}
在上述代码中,getResource方法根据传入的资源路径选择相应的Resource实现类,从而实现了策略模式的效果。不同的实现类负责不同类型资源的访问逻辑,使得Resource接口的使用更加灵活和便捷。
相关文章:
Spring中的适配器模式和策略模式
1. 适配器模式的应用 1.1适配器模式(Adapter Pattern)的原始定义是:将一个类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工作。 1.2 AOP中的适配器模式 在Spring的AOP中,使用Advice&#…...
书生浦语大模型实战营---Python task
任务一 请实现一个wordcount函数,统计英文字符串中每个单词出现的次数,通过构建defaultdict字典,可以避免插入值时需要判断值是否存在 from collections import defaultdictdef word_count(text):#构建缓存reval defaultdict(int)words t…...
Chrome 127内置AI大模型攻略
Chrome 127 集成Gemini:本地AI功能 Google将Gemini大模型整合进Chrome浏览器,带来全新免费的本地AI体验: 完全免费、无限制使用支持离线运行,摆脱网络依赖功能涵盖图像识别、自然语言处理、智能推荐等中国大陆需要借助魔法,懂都懂。 安装部署步骤: 1. Chrome V127 dev …...
Yolo的离线运行
Yolo 的离线运行 运行环境准备 比较简单的办法是通过官方的github获取到对应的yolo运行需要的python环境-requirement.txt.通过如下地址可以获取到对应的文件和相应的说明以及实例。 Yolov5 git地址 为了让程序能本地话运行,我们还需要获取相应的模型权重文件&…...
【矿井知识】煤矿动火作业
简介 煤矿动火作业是指在煤矿环境下进行的任何形式的使用火源的工作。这些工作可能包括焊接、切割、加热、打磨等操作,这些操作都可能产生火花、火焰或高温,因此被称为动火作业。 动火作业的主要类型 焊接:包括电弧焊、气焊等,…...
设计模式使用场景实现示例及优缺点(结构型模式——享元模式)
结构型模式 享元模式(Flyweight Pattern) 享元模式,作为软件设计模式中的一员,其核心目标在于通过共享来有效地支持大量细粒度对象的使用。在内存使用优化方面,享元模式提供了一种极为高效的路径,尤其在处…...
开放式耳机哪款比较好?五款开放式耳机测评推荐
开放式耳机真的越来越火了,真的好多人问我,开放式耳机应该怎么选啊,所以这次我亲自测评了几款开放式耳机,作为数码博主这一篇文章就教大家如何挑选开放式耳机,当然最后还有五款开放式耳机的推荐给到大家,话…...
【网络安全】实验三(基于Windows部署CA)
一、配置环境 打开两台虚拟机,并参照下图,搭建网络拓扑环境,要求两台虚拟的IP地址要按照图中的标识进行设置,并根据搭建完成情况,勾选对应选项。注:此处的学号本人学号的最后两位数字,1学号100…...
hive中reverse函数
目录 前言基本函数介绍实战 前言 reverse函数,是一个常用的字符串处理函数,很多编程语言都有。最近开发中,遇到一个reverse解决的需求,发现自己尚未总结过,遂补上。 基本函数介绍 SELECT reverse(string_column) FR…...
SimpleTrack环境配置教程
SimpleTrack环境配置教程 conda create --name SimpleTrack python3.6 conda activate SimpleTrack git clone https://github.com/tusen-ai/SimpleTrack.git cd ./SimpleTrack/ # pip install opencv-python4.5.4.58 # 安装opencv-python报错,可尝试安此版本 pip …...
frameworks 之Zygote
frameworks 之Zygote Zygote.rc 解析Zygote 启动ZygoteInit.javaZygote.cppLiunx fork Zygote 中文意思为受精卵。 和其意思一样,该功能负责android系统孵化service 和 app 进程。 本文讲解Zygote的大概流程。涉及的相同的类,如下所示 system/core/rootd…...
基于考研题库小程序V2.0实现倒计时功能板块和超时判错功能
V2.0 需求沟通 需求分析 计时模块 3.1.1、功能描述←计时模块用于做题过程中对每一题的作答进行30秒倒计时,超时直接判错,同时将总用时显示在界面上;记录每次做题的总用时。 3.1.2、接口描述←与判定模块的接口为超时判定,若单题用时超过 …...
idm站点抓取可以用来做什么 idm站点抓取能抓取本地网页吗 idm站点抓取怎么用 网络下载加速器
在下载工具众多且竞争激烈的市场中,Internet Download Manager(简称IDM)作为一款专业的下载加速软件,仍然能够赢得众多用户的青睐,这都要得益于它的强大的下载功能。我们在开始使用IDM的时候总是有很多疑问,…...
maven7——(重要,构建项目)maven项目构建(命令)
Maven的常用命令管理项目的生命周期 clean命令 清除编译产生的target文件夹内容,可以配合相应命令在cmd中使用,如mvn clean package, mvn clean test D:\工作\公司培训-4班\day20\day20\untitled1>mvn clean compile命令 该命令可以…...
容联云发布容犀大模型应用,重塑企业“营销服”|WAIC 2024
7月6日,在2024世界人工智能大会上,容联云成功举办主题为“数智聚合 产业向上”的生成式应用与大模型商业化实践论坛。 论坛上,容联云发布了容犀智能大模型应用升级,该系列应用包括容犀Agent Copilot、容犀Knowledge Copilot、容犀…...
Docker 安装字体文件
由于 Docker 容器的隔离性,与宿主机是独立的运行环境,如果需要用到宿主机的字体文件就需要进行安装。 例如在导出 PDF 文件时,如果缺少字体文件,就会产生乱码(常表现为中文变成方框)。 Docker 字体文件的安…...
C/C++ 移动追加内容到文件尾部。
1、通过C语言文件函数库 1.1、通过追加到尾部字符命令 FILE* f fopen(file_path.data(), "ab"); 1.2、不通过追加到尾部字符命令 FILE* f fopen(path, "rb"); if (NULL ! f) { fseek(f, 0, SEEK_END); } Unix 平台(Linux/Android/MacOS…...
ISO/OIS的七层模型②
OSI模型是一个分层的模型,每一个部分称为一层,每一层扮演固定的角色,互不干扰。OSI有7层,从上到下分别是: 一,每层功能 7.应用层(Application layer ):应用层功能&#x…...
美团到家平台业务探索
背景 到家业务发展已经近10年,目前最为火热的应该有美团到家、抖音到家等,这种极具挑战性的业务,值得学习和思考。 既然是服务平台化,那一定是兼容了多种业务以及多种模式。 挑战 订单、骑手规模大,供需匹配过程的…...
React -- useState状态更新异步特性——导致获取值为旧值的问题
useState状态异步更新 问题导致的原因解决办法进一步分析后续遇到的新问题 问题 const [isSelecting, setIsSelecting] useState(false);useEffect(() > {const handleKeyDown (event) > {if (event.key Escape) {if(isSelectingRef){//.......setIsSelecting(!isSele…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
