干翻Mybatis源码系列之第七篇:Mybatis提供的集成缓存方案

news2024/12/26 21:11:21

第一章:Mybatis Orm的缓存

Mybatis定义了一个对象缓存,是Mybatis对缓存的封装,为了屏蔽实现的差异,这被定义成了一个接口Interface,这样的话,Mybatis的缓存基本上是存储于JVM内存中的。

一:Cache源码

public interface Cache {
  String getId(); //每一个MapStatement都会有一个Cache,需要有一个编号。     
  void putObject(Object key, Object value); // 向缓存中添加
  Object getObject(Object key); // 从缓存中获取数据
  Object removeObject(Object key);//从缓存中删除数据
  void clear();//清空
  int getSize();//容量
  ReadWriteLock getReadWriteLock();//读写锁是解决并发解决的。

}

Cache整个的存储结构,很类似于Java中Map。他使用的是JVM的内存。类似于键值对的这种结构。

第二章:自写Cache实现类

一:Map做容器

实现方式1:存多个数据,并且存键值对的数据。基本上容器就是Map了。

public class MyMybatisCache implements Cache {

    private Map<Object,Object> internalCache  = new HashMap();

    @Override
    public String getId() {
        return getClass().getName() ;
    }

    @Override
    public void putObject(Object key, Object value) {
          internalCache.put(key,value);
    }

    @Override
    public Object getObject(Object key) {
        return internalCache.get(key);
    }

    @Override
    public Object removeObject(Object key) {
        return internalCache.remove(key);
    }

    @Override
    public void clear() {
        internalCache.clear();
    }

    @Override
    public int getSize() {
        return internalCache.size();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return new ReentrantReadWriteLock();
    }
}

二:Jedis做容器

实现方式2:存多个数据,并且存键值对的数据。这里使用Redis也是可以的。

public class MyMybatisCache2 implements Cache {
    @Override
    public String getId() {
        return null;
    }

    @Override
    public void putObject(Object key, Object value) {
        // redis java client  ---> jedis
         //Jedis jedis = JedisUtils.openJedis();
        //key ---> json  value--->json
        //jedis.set(String,String);
        //key --- byte[] value --- byte[]
        //jedis.set(byte[],byte[]);

        byte[] k = SerializationUtils.serialize((Serializable) key);
        byte[] v = SerializationUtils.serialize((Serializable) value);
        //jedis.set(k, v);
    }

    @Override
    public Object getObject(Object key) {
        if (key != null) {
            byte[] k = SerializationUtils.serialize((Serializable) key);
            //Jedis jedis = JedisUtils.openJedis();
           // byte[] bytes = jedis.get(k);
//            if(bytes !=null){
//                Object value = SerializationUtils.deserialize(bytes);
//                return value;
//            }
        }
        return null;
    }

    @Override
    public Object removeObject(Object key) {
        return null;
    }

    @Override
    public void clear() {

    }

    @Override
    public int getSize() {
        return 0;
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return null;
    }
}

org.apache.commons下的commons-lang3这个包是阿帕奇对于Java.lang包下的功能的增强(String、toString、equals、hashCode、Serializable…)

第三章:Mybatis的Cache实现类

以下是Mybatis的Cache实现类的截图:
在这里插入图片描述
Mybatis对于Cache的实现类大致位于两个包:org.apache.ibatis.cache.decorators,org.apache.ibatis.cache.impl

核心的Cache实现位于Impl包下:PerpetualCache,剩下的都是基于装饰器模式,(装饰器的核心目的是为了他的目标增加功能)所以这些装饰器都不是核心,这里的核心就是PerpetualCache。

一:核心PerpetualCache

public class PerpetualCache implements Cache {

  private final String id;

  private Map<Object, Object> cache = new HashMap<Object, Object>();

  public PerpetualCache(String id) {
    this.id = id;
  }

  @Override
  public String getId() {
    return id;
  }

  @Override
  public int getSize() {
    return cache.size();
  }

  @Override
  public void putObject(Object key, Object value) {
    cache.put(key, value);
  }

  @Override
  public Object getObject(Object key) {
    return cache.get(key);
  }

  @Override
  public Object removeObject(Object key) {
    return cache.remove(key);
  }

  @Override
  public void clear() {
    cache.clear();
  }

  @Override
  public ReadWriteLock getReadWriteLock() {
    return null;
  }

  @Override
  public boolean equals(Object o) {
    if (getId() == null) {
      throw new CacheException("Cache instances require an ID.");
    }
    if (this == o) {
      return true;
    }
    if (!(o instanceof Cache)) {
      return false;
    }

    Cache otherCache = (Cache) o;
    return getId().equals(otherCache.getId());
  }

  @Override
  public int hashCode() {
    if (getId() == null) {
      throw new CacheException("Cache instances require an ID.");
    }
    return getId().hashCode();
  }

}

底层使用HashMap来完成的,这个已经可以完成一个Cache基本的存储功能了。再次基础上想让Cache功能更强大,我们才用了装饰器的这样的Cache。

二:装饰器Cache

核心目标:为了让PerpetualCache的功能更加强大。

1:FifoCache和LruCache

增强了换出功能,换出功能最为核心的两种算法就是:Fifo先入先出,Lru最小使用。
Lru是默认的装饰器。

public class FifoCache implements Cache {

  private final Cache delegate;
  private final Deque<Object> keyList;
  private int size;

  public FifoCache(Cache delegate) {
    this.delegate = delegate;
    this.keyList = new LinkedList<Object>();
    this.size = 1024;
  }

  @Override
  public String getId() {
    return delegate.getId();
  }

  @Override
  public int getSize() {
    return delegate.getSize();
  }

  public void setSize(int size) {
    this.size = size;
  }

  @Override
  public void putObject(Object key, Object value) {
    cycleKeyList(key);
    delegate.putObject(key, value);
  }

  @Override
  public Object getObject(Object key) {
    return delegate.getObject(key);
  }

  @Override
  public Object removeObject(Object key) {
    return delegate.removeObject(key);
  }

  @Override
  public void clear() {
    delegate.clear();
    keyList.clear();
  }

  @Override
  public ReadWriteLock getReadWriteLock() {
    return null;
  }

  private void cycleKeyList(Object key) {
    keyList.addLast(key);
    if (keyList.size() > size) {
      Object oldestKey = keyList.removeFirst();
      delegate.removeObject(oldestKey);
    }
  }

}
public class LruCache implements Cache {

  private final Cache delegate;
  private Map<Object, Object> keyMap;
  private Object eldestKey;

  public LruCache(Cache delegate) {
    this.delegate = delegate;
    setSize(1024);
  }

  @Override
  public String getId() {
    return delegate.getId();
  }

  @Override
  public int getSize() {
    return delegate.getSize();
  }

  public void setSize(final int size) {
    keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
      private static final long serialVersionUID = 4267176411845948333L;

      @Override
      protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
        boolean tooBig = size() > size;
        if (tooBig) {
          eldestKey = eldest.getKey();
        }
        return tooBig;
      }
    };
  }

  @Override
  public void putObject(Object key, Object value) {
    delegate.putObject(key, value);
    cycleKeyList(key);
  }

  @Override
  public Object getObject(Object key) {
    keyMap.get(key); //touch
    return delegate.getObject(key);
  }

  @Override
  public Object removeObject(Object key) {
    return delegate.removeObject(key);
  }

  @Override
  public void clear() {
    delegate.clear();
    keyMap.clear();
  }

  @Override
  public ReadWriteLock getReadWriteLock() {
    return null;
  }

  private void cycleKeyList(Object key) {
    keyMap.put(key, key);
    if (eldestKey != null) {
      delegate.removeObject(eldestKey);
      eldestKey = null;
    }
  }

}

如何体现装饰器设计模式的:

    @Test
    public void test2() {
    	//原始核心Cache只有基本功能
        PerpetualCache perpetualCache = new PerpetualCache("sunshuai");
        //套一层之后,引入了换出功能
        LruCache lruCache = new LruCache(perpetualCache);
        //再次套一层之后,引入了日志功能。
        LoggingCache loggingCache = new LoggingCache(lruCache);
    }

本质上就是一个套娃的过程,所有的装饰器和他的目标继承都是这个吊样。

2:LoggingCache

简单说明:增加日志打印功能

3:BlockingCache

简单说明:增加同一时间只会有一个线程去缓存中找某个key的值。

4:ScheduleCache

简单说明:定期刷新缓存,一段时间之后就自动清空缓存,这里边可以设置一个时间间隔,大于时间间隔之后就直接清空缓存。尽量解决脏数据的问题。

5:SerializableCache

简单说明:自动完成key,value的序列化和反序列化的过程。

6:TransactionalCache

简单说明:加上这个装饰器之后,只有在事务操作成功时,才会对应数据放到缓存中。

7:SoftCache和WeakCache

简单说明:这两个基本上就是纯概念性的东西,根部用不到
弱引用:xxxxxx
软引用:Tomcat在设计HttpSession的时候使用的是软引用。

设计模式的区分:装饰器模式和代理设计模式:
装饰器设计模式:
Mybatis当中大量增加了装饰器设计模式,目标是为了核心目标拓展功能,使用套娃的方式,一层一层的增加拓展工功能。

代理设计模式:
为目标原始目标增加额外功能。

如何去区分和权衡呢?
装饰器和代理设计模式,他们的原始功能是不一样的,装饰器设计模式拓展的功能是他的本职工作,比方说Mybatis当中的装饰器模式,增强的是就是他的本质核心原始功能;而代理设计模式增加的是额外功能,跟他们本质原始功能是有根本区别的,比如说是对于Service增加了事务的功能,事务和我们原始Service的功能是不一致的,这是二者最本质的区别。

装饰器设计模式能套娃,代理设计模式不行,这样的描述对么?

一般代理很少套娃,但是不代表他不能套娃。代理也是可以套娃的,JDK的动态代理就可以实现。这里可以补充一下代码。

代理能做到无中生有
当你给我一个接口的时候,我只能通过动态代理这种方式帮你自动的创建接口的实现类,这件事装饰器做不了。最典型的就是SqlSesission中的getMapper();

GOF4人帮只提供了23中设计模式,除了这几种之后,还有委托设计模式…他们不属于23中经典的范畴。这些个设计模式他有这种开发中有这些特点:
1:Java开发中用不全23中设计模式。有些设计模式不适用于微服务和web开发
2:23中设计模式有很多很类似的东西,很像,这样的话,我们就需要区分,比如说我们的代理和装饰器。甚至,我们很多时候会把代理和装饰器和适配器做区分。
3:Mybatis当中还有工厂、建造者等等设计模式。

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

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

相关文章

信息技术服务知识笔记

一、运维 1、基础环境运维服务 对保证信息系统正常运行所必需的电力、空调、消防、安防等基础环境的运维。包括&#xff1a;机房电力、消防、安防等系统的理性检查及状态监控、相应支持、故障处理、性能优化等服务 2、硬件运维服务 对硬件设备&#xff08;网络、主机、存储…

6.2.1mnist _eval

之前在调试6.2.1mnist _eval代码的时候&#xff0c;出现了下面的错误 //下面不阐述本人遇到的错误&#xff0c;直接告诉大家解决办法&#xff08;以老师给的源代码进行演示&#xff09; 首先&#xff0c;打开第6章的源代码 //点击程序与数据拆分的文件夹&#xff0c; 并将三个…

3、Flutter项目搭建

一、搭建项目 1.1 搭建空壳项目 接上篇的项目搭建、本篇将继续搭建各个界面.当BottomNavigationBar搭建起来后,在各个界面,没有显示对应的元素,因此我们在包含它的Scaffold中,添加body,这样让每个界面撑起来.每次点击就切换对应的界面. 那么我们创建一个_RootPageState中的私…

【Python】scikit-plot可视化模型(含源代码)

文章目录 一、前言二、功能1&#xff1a;评估指标可视化2.1 scikitplot.metrics.plot_confusion_matrix2.2 scikitplot.metrics.plot_roc2.3 scikitplot.metrics.plot_ks_statistic2.4 scikitplot.metrics.plot_precision_recall2.5 scikitplot.metrics.plot_silhouette2.6 sci…

操作系统学习01

1、什么是操作系统&#xff1f; 通过以下四点可以概括操作系统到底是什么&#xff1a; 操作系统&#xff08;Operating System&#xff0c;简称 OS&#xff09;是管理计算机硬件与软件资源的程序&#xff0c;是计算机的基石。操作系统本质上是一个运行在计算机上的软件程序 &a…

微前端 qiankun@2.10.5 源码分析(一)

微前端 qiankun2.10.5 源码分析&#xff08;一&#xff09; 前言 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。 Techniques, strategies and recipes for building a modern web app with multiple teams that can ship feat…

Figma转换为sketch,分享这3款工具

在我们的设计工作中&#xff0c;我们经常会遇到各种各样的设计文件相互转换的问题。 你经常为此头疼吗&#xff1f;当你遇到Figma转换Sketch文件的问题时&#xff0c;你是如何解决的&#xff1f;Figma转换Sketch文件有工具吗&#xff1f; 根据众多设计师的经验&#xff0c;本…

在竞争激烈的移动应用市场中获得成功,掌握决胜Framework技术

为何要学习framework&#xff1f; Framework&#xff0c;指的是对应用程序开发所需的核心工具和组件的封装和提供。在Android开发中&#xff0c;Framework是整个开发过程中的核心组成部分&#xff0c;提供了许多功能和服务&#xff0c;包括UI组件、数据存储、网络通信、多媒体…

第二十四章 策略模式

文章目录 前言传统方式解决鸭子问题完整代码抽象鸭子类野鸭子类北京鸭子类玩具鸭子类 一、策略模式基本介绍二、策略模式解决鸭子问题完整代码飞翔接口 FlyBehavior飞翔接口的子类实现飞翔技术高超 GoodFlyBehavior不会飞翔 NoFlyBehavior飞翔技术一般 BadFlyBehavior其他行为接…

文献阅读 Meta-SR: A Magnification-Arbitrary Network for Super-Resolution

题目 Meta-SR: A Magnification-Arbitrary Network for Super-Resolution Meta-SR: 用于超分辨率的任何放大网络 摘要 由于DCNN的发展&#xff0c;最近关于超分辨率的研究取得了巨大成功。然而&#xff0c;任意比例因子的超分辨率长期以来一直被忽视。以往的研究者大多将不同…

Stable-Diffusion AI画画本地搭建详细步骤

ChatGPT出来后&#xff0c;第一次感觉到人工智能真的可能要来了&#xff0c;因此也顺便尝试了下开源AI画画的搭建。网络上写的教程总是不那么面面俱到&#xff0c;因此本文参考了3篇文章才成功把Stable-Diffusion 本地搭建搭建了起来。参考教程在文末。 本文是本地搭建AI画画&a…

C/C++内存泄露检查利器—valgrind

1、Valgrind概述 Valgrind是一套Linux下&#xff0c;开放源代码&#xff08;GPL V2&#xff09;的仿真调试工具的集合。 Valgrind由内核&#xff08;core&#xff09;以及基于内核的其他调试工具组成。内核类似于一个框架&#xff08;framework&#xff09;&#xff0c;它模拟…

Android中的GPS开发

GPS简介 Gobal Positioning System&#xff0c;全球定位系统&#xff0c;是美国在20世纪70年代研制的一种以人造地球卫星为基础的高精度无线电导航的定位系统&#xff0c;它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间信息&#xff1b;它是具有…

2023年房地产抵押贷款研究报告

第一章 概述 房地产抵押贷款是一种以房地产为抵押品的贷款形式&#xff0c;包括个人和企业两种情况。个人房地产抵押贷款是指个人将名下房产作为抵押品向银行或其他金融机构申请贷款&#xff0c;而企业房地产抵押贷款则是指企业将自己名下的商业房产作为抵押品向金融机构申请贷…

202309读书笔记|《野性之美:非洲野生动物初窥》——走进自然界的野性之美

《野性之美: 非洲野生动物初窥》微读的一本书&#xff0c;图片居多&#xff0c;非常有视觉上的震撼。拍摄者也是我们孙姓的一员&#xff0c;孙长智。正如作者所说&#xff0c;与自然对话&#xff0c;你会感悟到生命之美、竞争之美、进化之美、和谐之美&#xff01; 我喜欢自然…

SPSS如何绘制常用统计图之案例实训?

文章目录 0.引言1.绘制简单条形图2.绘制分类条形图3.绘制分段条形图4.绘制简单线图5.绘制多重线图6.绘制垂直线图7.绘制简单面积图8.绘制堆积面积图9.绘制饼图10.绘制直方图11.绘制简单散点图12.绘制重叠散点图13.绘制矩阵散点图14.绘制三维散点图15.绘制简单箱图16.绘制分类箱…

【markdown工具配合图床】PicGo图床配置教程,一秒读懂配置

前言 看到这篇文章的大佬&#xff0c;我默认大家都会配置git&#xff0c;已经配置好ssh公钥。 此时你看到的这篇文章就是基于markdown工具&#xff08;VSCode&#xff0c;Typora&#xff09;编写的。 PicGo作为图床转换工具&#xff0c;并配合gitee作为图片服务器&#xff0…

java元注解和自定义注解的区别

Java的元注解和自定义注解是两个不同的概念。 元注解是Java内置的一组用于修饰其他注解的注解&#xff0c;包括Retention、Target、Inherited和Documented。它们可以控制被修饰的注解的保留策略、目标范围、是否继承等属性&#xff0c;并且可以在编写自定义注解时使用。 Retent…

国考省考结构化面试:综合分析题,社会现象(积极消极政策)、名言哲理(警句观点启示)、漫画反驳题等

国考省考结构化面试&#xff1a;综合分析题&#xff0c;社会现象&#xff08;积极消极政策&#xff09;、名言哲理&#xff08;警句观点启示&#xff09;、漫画反驳题等 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&…

【Java数据结构】优先级队列(堆)

优先级队列&#xff08;堆&#xff09; 概念模拟实现堆的概念堆的存储方式堆的创建向下调整堆的创建建堆的时间复杂度 堆的插入和删除堆的插入堆的删除 用堆模拟实现优先级队列 常用接口PriorityQueue的特性PriorityQueue常用接口介绍构造方法插入/删除/获取优先级最高的元素 P…