Spring中的适配器模式和策略模式

news2024/9/23 21:29:15

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 {
    @Override
    public void doSomething() {
        System.out.println("Doing something ...");
    }
}

// 使用Advice(通知)来增强被代理类的功能
public class MyBeforeAdvice implements MethodBeforeAdvice {
    // 在目标方法执行前进行拦截
    @Override
    public 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();
    }
}

每个类对应适配器模式中的如下角色:

  1. TargetMyServiceImpl类是目标对象,即需要被代理的对象。
  2. AdapterMyBeforeAdviceAdapter类是适配器对象,它将 MyBeforeAdvice对象适配为一个 MethodBeforeAdviceInterceptor对象,使得 MyBeforeAdvice可以被应用到目标对象的代理中。
  3. AdapteeMyBeforeAdvice类是被适配的对象,它定义了一个前置通知方法,在目标方法执行前进行拦截。
  4. ClientTest01类是客户端,它通过创建适配器对象并将其添加到目标对象的代理中,实现了在目标方法执行前应用 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,否则创建UrlResource
            URL 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接口的使用更加灵活和便捷。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1921101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DP V2.1a标准学习(二)

三、线材&连接器要求 1.线材分类 线材按照支持速率的不同,划分为不同规格,具体如下: DP和USB线材混用矩阵,也就是不同规格的线材对应的支持传输速率和传输类型,如下: 2.线材和连接器组件分类 线材+连接器组件分类与DP V1.4类似,不过型号更多了,如下: 也支持2种…

ss工具dump出vsock 端口号异常分析

端口冲突时,会出现bind fail异常,这时可以用ss --vsock -pl命令dump出所有listen状态的vsock,但实际发现传入的9000端口,dump出来却是10275,如下图: 难道是内核把端口改了?分析内核态源码,ss最终…

SW - 将面导出为dxf

文章目录 SW - 将面导出为dxf概述笔记原点问题END SW - 将面导出为dxf 概述 在做PCB板框. 以前做过一个笔记,用autoCAD来制作导出dxf(cadence SPB17.4 - 用autoCAD2022画一个PCB板框)。 不喜欢用autoCAD(相对麻烦), 还是喜欢用SW&#xff0…

js 中 new Worker 报错 Failed to construct ‘Worker‘

new Worker("worker.js");运行多线程 Web Worker 的时候报错 Uncaught DOMException: Failed to construct ‘Worker’ 原因是浏览器不允许通过本地文件访问使用Web Worker。 解决方法: 将项目部署到服务器上或者用Node起本地服务访问项目

从本地到全局:基于图的RAG方法进行查询聚焦原理摘要

摘要 使用检索增强生成(RAG)从外部知识源检索相关信息,使大型语言模型(LLMs)能够回答有关私有和/或以前未见过的文档集合的问题。然而,当针对整个文本文档库提出全局问题时,例如“数据集中的主…

45、tomcat+课后实验

tomcat 1、tomcat tomcat和php一样,都是用来处理动态页面的。 tomcat也可以作为web应用服务器,开源的。 php .php tomcat .jsp nginx .html tomcat 是用Java代码写的程序,运行的是Java的web应用程序。 tomcat的特点和功能&#xff1a…

推荐算法——NDCG归一化折扣累积增益

NDCG,全称为归一化折扣累积增益(Normalized Discounted Cumulative Gain),是一种常用的衡量搜索引擎和推荐系统结果质量的指标。NDCG考虑了结果的相关性和结果的排名位置,其值在0到1之间,值越大表示搜索结果…

解码RAG:智谱 RAG 技术的探索与实践

智谱 AI 长期专注于大模型技术的研究,从 23 年开始,大模型受到了各行各业的关注,智谱 AI 也深度的参与到各种场景的大模型应用的建设当中,积累了丰富的模型落地应用的实战经验,其中 RAG 类应用占据了较大的比重。 所谓…

【前端项目笔记】10 项目优化上线

项目优化上线 目标:优化Vue项目部署Vue项目(上线提供使用) 项目优化 项目优化策略: 生成打包报告:根据生成的报告发现问题并解决第三方库启用CDN:提高首屏页面的加载效率Element-UI组件按需加载路由懒加…

直观易用的大模型开发框架LangChain,你会了没?

目录 简介基本组件小试牛刀关于沟通代码案例:调用Embedding、Completion、Chat Model总结 目前LangChain框架在集团大模型接入手册中的学习案例有限,为了让大家可以快速系统地了解LangChain大模型框架并开发,产出此文章。本文章包含了LangCha…

SAP各代增强介绍与查找,这一篇就够了

目录 1.前言: 2.什么是增强: 3.增强类型: 4.增强查找方式: USER-EXIT的快速查找 ①基于源码查找 ②基于SPRO查找 ③通过SAT运行分析进行查找 Customer-Exit的快速查找 ①使用MODX_FUNCTION_ACTIVE_CHECK查找 ②使用/H …

Mysql:FIND_IN_SET 函数在逗号分隔的列表中搜索指定的值

FIND_IN_SET 函数用于在逗号分隔的列表中搜索指定的值。 语法: FIND_IN_SET(str,strlist),其中 str是要查找的值, strlist是逗号分隔的列表。函数返回值是 str在 strlist中的位置,位置从1开始,如果找不到则返回0 SELEC…

Linux桌面溯源

X窗口系统 Linux起源于X窗口系统(X Window System),亦即常说的X11,因其版本止于11之故。 X窗口系统(X Window System,也常称为X11或X)是一种以位图方式显示的软件窗口系统。最初是1984年麻省理…

论文AIGC率超标?一键降重快速搞定

如何有效降低AIGC论文的重复率,也就是我们说的aigc如何降重?AIGC疑似度过高确实是个比较愁人的问题。如果你用AI帮忙写了论文,就一定要在交稿之前做一下AIGC降重的检查。一般来说,如果论文的AIGC超过30%,很可能会被判定…

无线麦克风什么牌子音质好,轻揭秘什么牌子麦克风唱歌效果最好

​随着领夹麦克风市场的变革和技术突破,其在网络直播、视频拍摄和内容创作等领域的应用也日益广泛。我们注意到许多消费者在选购领夹无线麦克风时面临困惑,因此,我们将提供详细的购买指南,并推荐几款实用的麦克风,以供…

MFC Ribbon菜单 - 中英文实时切换方法

简介 最近在搞一个老外的项目,本来谈的好好的,纯英文界面。项目接近尾声了,又提出了中英文实时切换的新需求,没办法就只能想办法,毕竟客户最大嘛。 实现方法 还好本来的ribbon英文菜单不复杂,就用纯C编码…

解决QRCode生成二维码打印不出

问题:二维码嵌入在页面中,打印时二维码不渲染的情况 解决方法: 使用 html2canvas 库将指定的 DOM 元素(在这个例子中是 id 为 pdf 的元素)转换成一个画布(canvas),然后将这个画布转换…

数据库系统原理练习 | 作业2-第2章关系数据库(附答案)

整理自博主本科《数据库系统原理》专业课完成的课后作业,以便各位学习数据库系统概论的小伙伴们参考、学习。 *文中若存在书写不合理的地方,欢迎各位斧正。 专业课本: 目录 一、选择题 二、填空题 三、简答题 四、关系代数 1.课本p70页&…

嵌入式基础 接口协议汇总

在此收集整理嵌入式通信中常见的接口协议,它们具有一定的通用性,在今后的开发中会反复遇到。 包括但不限于以下类别(逐步完善中…): GPIOUARTSPII2CUSBEthernetNAND Flash类SDRAM类(ram-like)LC…

拉取DockerHub镜像

参考博主:http://t.csdnimg.cn/i49ET 方法一(不太行): 在daemon.json文件中添加一些国内还在服务的镜像站(可能某些镜像会没有) ([ -f /etc/docker/daemon.json ] || mkdir -p /etc/docker) && e…