当前位置: 首页 > news >正文

适配器模式是个啥,在Spring中又用来干啥了?

作用

将一个接口转换为客户端期望的另一个接口,适配器允许接口不兼容的类一起工作。

例子

  • 将内存卡的图片传输到电脑上,需要有一个适配器将内存卡可以插到电脑上,这里的适配器其实就是读卡器
  • 电源适配器:三脚插头无法连接两脚插座,因此需要一个电源适配器进行兼容
  • 翻译:将一个人说的话翻译给另一个人

大白话

适配器模式允许在适配器中包装一个原本不兼容的对象,以使其与另一个类兼容。

维基百科

通常用于使现有类在不修改其源代码的情况下与其他类一起使用。

使用场景

  • 想使用现有的类,但是它的接口与需要的不匹配
  • 想创建一个与不相干或者不可预见的类合作的可重用类,即不一定具有兼容接口的类
  • 大多数的第三方库的应用程序都使用适配器作为应用程序和第三方库之间的中间层,以将应用程序从库中分离出来,如果必须使用另一个库,则只需要新库的适配器,而无需更改应用程序代码

在Spring框架中的使用

在Spring Bean的生命周期中,有初始化方法和销毁之前执行的方法,销毁方法的注册执行就使用了适配器模式,众所周知,我们可以通过在xml中配置destroy-method和实现DisposableBean接口来完成配置,虽然这是两种完全不同的配置方式,但是Spring在设计的时候就将两种方式的配置最终都通过适配器的方式完成了整合,使得在IOC容器调用的时候完全无感,具体的看代码,项目源码:

//在容器中定义了一个Map保存所有实现DisposableBean的Bean
private Map<String, DisposableBean> disposableBeanMap = new HashMap<>();
//定义了适配器,显然这种方式是为了把xml配置的方式适配为DisposableBean的形式
//适配器内部定义了执行bean和具体的销毁方法
public class DisposableBeanAdapter implements DisposableBean {

    private final Object bean;

    private final String beanName;

    private String destroyMethodName;
	
    //构造方法中通过将BeanDefinition传入,获取到在xml中定义的destroy-method
    //
    public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) {
        this.bean = bean;
        this.beanName = beanName;
        this.destroyMethodName = beanDefinition.getDestroyMethodName();
    }

    //在真正执行销毁逻辑时,判断持有的bean是否实现了DisposableBean,实现了就直接执行销毁方法
    //否则就通过反射获取到destroyMethodName的方法,再执行,这样就实现了对两种方式的适配整合
    @Override
    public void destroy() throws Exception {
        //实现接口(DisposableBean)的方式
        if (bean instanceof DisposableBean) {
            //执行销毁方法
            ((DisposableBean)bean).destroy();
        }

        //xml定义destroy-method方式
        // !(bean instanceof DisposableBean) 防止二次执行销毁方法
        if(StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean)){
            Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
            if(destroyMethod == null){
                throw new BeansException("未找到destroy method:" + destroyMethodName + ",beanName:" + beanName);
            }
            destroyMethod.invoke(bean);
        }
    }
}
//在使用的时候只需要将
if(bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())){
            registryDisposableBean(beanName,new 	    DisposableBeanAdapter(bean , beanName , beanDefinition));
}

相关文章:

  • 183. 从不订购的客户—not in()、左连接
  • LED灯实验
  • vue中ref的作用
  • JSP简介
  • 湖仓一体电商项目(八):业务实现之编写写入ODS层业务代码
  • 基于深度学习的多人步态识别系统(YOLOV5+DeepSort+GaitSet+Segmentation)
  • 计算机网络——组成、分类、性能指标、分层结构
  • 【小程序】组件化开发的基本使用(二)
  • 【IVI】15.1.6 系统稳定性优化篇(LMKD 六)Vmpressure监视器初始化及其工作原理
  • 分享程序员面试的7个技巧
  • 市政管理学考试复习资料
  • c语言数据结构 二叉树(三)
  • 汉明码原理
  • 黑马瑞吉外卖之菜品信息的修改
  • 【Vue 基础知识】v-for的使用和注意事项
  • Android组件 - 收藏集 - 掘金
  • maya建模与骨骼动画快速实现人工鱼
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 初识 beanstalkd
  • 浮现式设计
  • 机器学习 vs. 深度学习
  • 入门到放弃node系列之Hello Word篇
  • 使用API自动生成工具优化前端工作流
  • 正则表达式小结
  • kubernetes资源对象--ingress
  • raise 与 raise ... from 的区别
  • 整理一些计算机基础知识!
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • ​queue --- 一个同步的队列类​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (Java数据结构)ArrayList
  • (solr系列:一)使用tomcat部署solr服务
  • (阿里云万网)-域名注册购买实名流程
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (接口自动化)Python3操作MySQL数据库
  • (四)模仿学习-完成后台管理页面查询
  • (一)kafka实战——kafka源码编译启动
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .Net mvc总结
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET面试题(二)
  • /proc/vmstat 详解
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @RequestParam详解
  • [1]-基于图搜索的路径规划基础
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Android]RecyclerView添加HeaderView出现宽度问题