Mybatis缓存机制(二)尝试自己构建Cache责任链

内容概要

本篇博客是在Mybatis缓存机制(一)的基础上,自己手写Cache链,会去除Cache内容以外的代码,尽可能的还原MyBatis关于Cache的内容。

代码编写

Cache接口以及Cache实现类

  1. 新建一个Empty Module叫CacheImplement,新建package mybatis.cache
    在这里插入图片描述
  2. 既然要实现Cache的相关功能,那么首先定义Cache的接口
package mybatis.cache;
/*
* @author:算法菜鸟飞高高
* @version:1.0
* @since:1.0
* */
public interface Cache {
    // cache对象需要有自己的id,用getId返回它
    String getId();
    // 往缓存中添加数据
    void putObject(Object key, Object value);
    // 通过key取数据
    Object getObject(Object key);
    //通过key删除数据
    void removeObject(Object key);
    //清楚缓存中的所有数据
    void clear();
    //获取缓存中数据的个数
    int getSize();
}

接口的方法与Mybatis中的几乎相同

  1. 实现基础Cache PerpetualCache,在mybatis.cache下新建class perpetualCache
package mybatis.cache;

import java.util.HashMap;
import java.util.Map;

public class PerpetualCache implements Cache{
    private String id;
    // 底层使用一个HashMap来存储缓存数据, get, put,size,remove,clear操作都是基于这个map
    private Map<Object, Object> caches;
    public PerpetualCache(String id) {
        this.id = id;
        caches = new HashMap<>();
    }

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

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

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

    @Override
    public void removeObject(Object key) {
        this.caches.remove(key);
    }

    @Override
    public void clear() {
        this.caches.clear();
    }

    @Override
    public int getSize() {
        return this.caches.size();
    }
}
  1. 实现SynchrolizedCache作为我们的decorator Cache,因为我们的关注点不在具体Cache实现的功能,而是责任链的应用,所以就先实现一个最简单的。
package mybatis.cache;

public class SynchrolizedCache implements Cache{
	// 持有责任链的下一个Cache结点
    private Cache delegate;

    public SynchrolizedCache(Cache delegate) {
        this.delegate = delegate;
    }

    @Override
    public  String getId() {
        return delegate.getId();
    }
	// 对于所有修改以及访问map的方法都需要加synchronized修饰
    @Override
    public synchronized void putObject(Object key, Object value) {
        delegate.putObject(key, value);
    }

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

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

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

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

CacheBuilder创建

目前我们实现了Cache接口,以及它的两个实现类,已经可以编写创建CacheBuilder类了。

public class CacheBuilder{
	// 一个责任链对应一个id,这个后面Base Cache的构造器需要
	private String id;
	public CacheBuilder(String id){
		this.id = id;
	}
	// 这个表示Base Cache,他与其它Cache的区别在于构造器上,它的构造器接受一个id,如PerpetualCache
	//其它的Cache构造器接受另一个Cache对象,如SynchrolizedCache
	private Class<? extends Cache>implement;
	//用来保存责任链中所有的decorator Class
	private ArrayList<Class<? extends Cache>> decorators = new ArrayList<>();
	public CacheBuilder setImplement(Class<? extends Cache> implement){
		this.implement = implement;
		return this; // 返回this对象,使得用户可以链式调用方法
	}
	// 往责任链添加结点的方法
	public CacheBuilder addDecorator(Class<? extends Cache> decorator){
			if(decorator != null)
				decorators.add(decorator);
			return this;
	}
	// 利用Class对象生成Base Cache的方法
	 private Cache baseCacheInstance(String id){
	 // 声明一个Cache类的构造器
        Constructor<? extends Cache> baseConstructor;
        try {
        	//获得参数是String类型的构造器
            baseConstructor = implement.getConstructor(String.class);
            //利用构造器创建实例并返回
            Cache cache = baseConstructor.newInstance(id);
            return cache;
        } catch (Exception e) {
            throw new RuntimeException("cache " + implement.getName() + " build error " + e);
        }
    }
 	// 利用decorator的Class对象生成 Cache对象,与baseCacheInstance功能相同,区别是这个要求构造器
 	// 接受一个Cache类型的参数
    private Cache decoratorInstance(Class<? extends Cache> decorator, Cache cache){
        Constructor<? extends Cache> decoratorConstructor;
        try {
            decoratorConstructor = decorator.getConstructor(Cache.class);
            Cache decoratorCache = decoratorConstructor.newInstance(cache);
            return decoratorCache;
        } catch (Exception e) {
            throw new RuntimeException("decorator " + decorator.getName() + " build error " + e);
        }
    }
    //构造责任链
    public Cache build(){
        // 保证Implement被赋值
        setDefalutImplement();
        //创建基础的Cache
        Cache cache = baseCacheInstance(id);
        //往责任链中添加Cache
        for(Class<? extends  Cache> decorator : decorators){
            cache = decoratorInstance(decorator, cache);
        }
        return cache;
    }
    private void setDefalutImplement(){
       if(implement == null)
            setImplement(PerpetualCache.class);
    }
}

测试CacheBuilder的效果

在package mybatis.pojo下创建Student类,作为缓存的数据。

package mybatis.pojo;

public class Student {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在mybatis.test创建TestCacheBuilder类用来测试CacheBuilder

package mybatis.test;

import mybatis.cache.Cache;
import mybatis.cache.CacheBuilder;
import mybatis.cache.SynchrolizedCache;
import mybatis.pojo.Student;

public class TestCacheBuilder {
    public static void main(String[] args) {
        Cache cache = new CacheBuilder("test").addDecorator(SynchrolizedCache.class).build();
        cache.putObject(1, new Student("zhangsan", 24));
        System.out.println(cache.getObject(1));
    }
}

在这里插入图片描述

分析CacheBuilder的设计优势

CacheBuilder几乎不依赖任何一个具体的Cache类,只有但用户没有指定implement时,才会使用PerpetualCache,利用反射的Constructor,可以实例化任何一个满足要求的decorator Cache。链式调用法则也方便了用户的使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值