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

78 阅读3分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

作用

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

例子

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

大白话

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

维基百科

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

使用场景

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

在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));
}