自定义Mybatis二级缓存-上

来源:互联网 发布:美丽港发型设计软件 编辑:程序博客网 时间:2024/05/01 13:51

前言

        Mybatis,是最常用的ORM框架之一。而缓存,也是我们在日常的工作中遇到的重要问题,这两者的结合实际上就落在了其自带的缓存上。
        下面,阿福带着大家去探索如何自定义Mybatis二级缓存。

二级缓存是什么?

        实际上,Mybatis共有两级缓存,其一级缓存就是针对于一次会话的,一旦会话结束了,缓存的历史使命也就结束了。当然,它是存储在本地机器的内存中的,你知道的,这势必造成了一个问题,那就是多机器缓存的共享问题,你想一想,现在谁家的应用是一台机器就能撑起来的。所以,这里就轮到我们的二级缓存出场了。
        二级缓存的一个比较明显的优势就是它是基于一个namespace的,额,你问我这是啥?我只能说,百度一下,你就知道。其还支持自定义的实现,要不然,本文的还怎么往下写!
        实际上,Mybatis为我们提供了一个接口用来进行二级缓存的扩展,这个接口就是org.apache.ibatis.cache.Cache。对,就是这个接口,我们先一起来看看这个接口吧!代码如下:

/** *    Copyright 2009-2015 the original author or authors. * *    Licensed under the Apache License, Version 2.0 (the "License"); *    you may not use this file except in compliance with the License. *    You may obtain a copy of the License at * *       http://www.apache.org/licenses/LICENSE-2.0 * *    Unless required by applicable law or agreed to in writing, software *    distributed under the License is distributed on an "AS IS" BASIS, *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *    See the License for the specific language governing permissions and *    limitations under the License. */package org.apache.ibatis.cache;import java.util.concurrent.locks.ReadWriteLock;/** * SPI for cache providers. *  * One instance of cache will be created for each namespace. *  * The cache implementation must have a constructor that receives the cache id as an String parameter. *  * MyBatis will pass the namespace as id to the constructor. *  * <pre> * public MyCache(final String id) { *  if (id == null) { *    throw new IllegalArgumentException("Cache instances require an ID"); *  } *  this.id = id; *  initialize(); * } * </pre> * * @author Clinton Begin */public interface Cache {  /**   * @return The identifier of this cache   */  String getId();  /**   * @param key Can be any object but usually it is a {@link CacheKey}   * @param value The result of a select.   */  void putObject(Object key, Object value);  /**   * @param key The key   * @return The object stored in the cache.   */  Object getObject(Object key);  /**   * As of 3.3.0 this method is only called during a rollback    * for any previous value that was missing in the cache.   * This lets any blocking cache to release the lock that    * may have previously put on the key.   * A blocking cache puts a lock when a value is null    * and releases it when the value is back again.   * This way other threads will wait for the value to be    * available instead of hitting the database.   *   *    * @param key The key   * @return Not used   */  Object removeObject(Object key);  /**   * Clears this cache instance   */    void clear();  /**   * Optional. This method is not called by the core.   *    * @return The number of elements stored in the cache (not its capacity).   */  int getSize();  /**    * Optional. As of 3.2.6 this method is no longer called by the core.   *     * Any locking needed by the cache must be provided internally by the cache provider.   *    * @return A ReadWriteLock    */  ReadWriteLock getReadWriteLock();}

        代码不是很多,主要定义了一些方法,但是注意看!

/** * SPI for cache providers. *  * One instance of cache will be created for each namespace. *  * The cache implementation must have a constructor that receives the cache id as an String parameter. *  * MyBatis will pass the namespace as id to the constructor. *  * <pre> * public MyCache(final String id) { *  if (id == null) { *    throw new IllegalArgumentException("Cache instances require an ID"); *  } *  this.id = id; *  initialize(); * } * </pre> * * @author Clinton Begin */

        这个接口的头顶的这段注释非常重要,它是这样说的,每一个namespace都将会有这样的一个实例。但是呢,这个实现接口的实现类必须有他要求的这个构造方法,这个构造方法呢实际上会接受一个id,这个id就是缓存时候的标示。
最后,还给了一段代码描述之。
        然后仔细的看下面的方法,无非就是放入缓存,得到缓存内容,移除缓存、清掉缓存全部内容、换区缓存的大小、还有就是读写加锁。
        然后,我们就照猫画虎来写一个呗!实际上,我们不着急动手,你知道的,


6


        上面的截图是我们的mybytis给我们的官方的一个简单实现,让我们去研究研究,然后开始动手。

/** *    Copyright 2009-2015 the original author or authors. * *    Licensed under the Apache License, Version 2.0 (the "License"); *    you may not use this file except in compliance with the License. *    You may obtain a copy of the License at * *       http://www.apache.org/licenses/LICENSE-2.0 * *    Unless required by applicable law or agreed to in writing, software *    distributed under the License is distributed on an "AS IS" BASIS, *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *    See the License for the specific language governing permissions and *    limitations under the License. */package org.apache.ibatis.cache.impl;import java.util.HashMap;import java.util.Map;import java.util.concurrent.locks.ReadWriteLock;import org.apache.ibatis.cache.Cache;import org.apache.ibatis.cache.CacheException;/** * @author Clinton Begin */public class PerpetualCache implements Cache {  private 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做缓存,阿偶,实际上我们只要把这个里面的写入HashMap和读取的操作换成别的一种存储方式,当然,想换成什么是你的自由。我们不就实现了二级缓存的自定义。

总结

        好了,马上就要吃饭了。今天的话利用早上的这点时间详细的看了下Mybatis二级缓存为我们预留的接口,然后看了其默认的实现类。官方的教材才是最完整的。下一篇我们将会来实现redis作为Mybatis二级缓存。敬请期待!

1 0
原创粉丝点击