mybatis 缓存

  • Author: HuiFer
  • Description: 该文介绍 mybatis Cache 源码
  • 源码阅读工程: SourceHot-Mybatis

  • org.apache.ibatis.cache.Cache

  1. public interface Cache {
  2. String getId();
  3. /**
  4. * 放入数据
  5. */
  6. void putObject(Object key, Object value);
  7. /**
  8. * 获取数据
  9. */
  10. Object getObject(Object key);
  11. /**
  12. * 移除数据
  13. */
  14. Object removeObject(Object key);
  15. /**
  16. * 清空数据
  17. */
  18. void clear();
  19. /**
  20. * 有多少缓存数据
  21. */
  22. int getSize();
  23. /**
  24. * 重入锁
  25. * @return A ReadWriteLock
  26. */
  27. default ReadWriteLock getReadWriteLock() {
  28. return null;
  29. }
  30. }
  • BlockingCache: 阻塞的缓存
  • FifoCache: 按对象进入缓存的顺序来移除它们。
  • LruCache: 最近最少使用的:移除最长时间不被使用的对象。
  • SoftCache: 软引用:移除基于垃圾回收器状态和软引用规则的对象
  • WeakCache: 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

BlockingCache

  • BlockingCache 内部使用了ReentrantLock来进行加锁开锁这个操作.在插入缓存时上锁,插入缓存后释放.请求缓存值得时候同理
  1. public class BlockingCache implements Cache {
  2. private final Cache delegate;
  3. /**
  4. * 线程安全的map
  5. */
  6. private final ConcurrentHashMap<Object, ReentrantLock> locks;
  7. private long timeout;
  8. public BlockingCache(Cache delegate) {
  9. this.delegate = delegate;
  10. this.locks = new ConcurrentHashMap<>();
  11. }
  12. @Override
  13. public String getId() {
  14. return delegate.getId();
  15. }
  16. @Override
  17. public int getSize() {
  18. return delegate.getSize();
  19. }
  20. @Override
  21. public void putObject(Object key, Object value) {
  22. try {
  23. delegate.putObject(key, value);
  24. } finally {
  25. releaseLock(key);
  26. }
  27. }
  28. @Override
  29. public Object getObject(Object key) {
  30. acquireLock(key);
  31. Object value = delegate.getObject(key);
  32. if (value != null) {
  33. // 释放锁
  34. releaseLock(key);
  35. }
  36. return value;
  37. }
  38. @Override
  39. public Object removeObject(Object key) {
  40. // despite of its name, this method is called only to release locks
  41. releaseLock(key);
  42. return null;
  43. }
  44. @Override
  45. public void clear() {
  46. delegate.clear();
  47. }
  48. private ReentrantLock getLockForKey(Object key) {
  49. return locks.computeIfAbsent(key, k -> new ReentrantLock());
  50. }
  51. /**
  52. * 请求锁
  53. * @param key
  54. */
  55. private void acquireLock(Object key) {
  56. Lock lock = getLockForKey(key);
  57. if (timeout > 0) {
  58. try {
  59. // 上锁
  60. boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
  61. if (!acquired) {
  62. throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId());
  63. }
  64. } catch (InterruptedException e) {
  65. throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e);
  66. }
  67. } else {
  68. lock.lock();
  69. }
  70. }
  71. /**
  72. * 释放锁
  73. * @param key
  74. */
  75. private void releaseLock(Object key) {
  76. ReentrantLock lock = locks.get(key);
  77. if (lock.isHeldByCurrentThread()) {
  78. lock.unlock();
  79. }
  80. }
  81. public long getTimeout() {
  82. return timeout;
  83. }
  84. public void setTimeout(long timeout) {
  85. this.timeout = timeout;
  86. }
  87. }

FifoCache

  • 存储结构是java.util.LinkedList
  1. public class FifoCache implements Cache {
  2. private final Cache delegate;
  3. /**
  4. * 队列
  5. */
  6. private final Deque<Object> keyList;
  7. private int size;
  8. public FifoCache(Cache delegate) {
  9. this.delegate = delegate;
  10. this.keyList = new LinkedList<>();
  11. this.size = 1024;
  12. }
  13. @Override
  14. public String getId() {
  15. return delegate.getId();
  16. }
  17. @Override
  18. public int getSize() {
  19. return delegate.getSize();
  20. }
  21. public void setSize(int size) {
  22. this.size = size;
  23. }
  24. @Override
  25. public void putObject(Object key, Object value) {
  26. cycleKeyList(key);
  27. delegate.putObject(key, value);
  28. }
  29. @Override
  30. public Object getObject(Object key) {
  31. return delegate.getObject(key);
  32. }
  33. @Override
  34. public Object removeObject(Object key) {
  35. return delegate.removeObject(key);
  36. }
  37. @Override
  38. public void clear() {
  39. delegate.clear();
  40. keyList.clear();
  41. }
  42. /**
  43. * 添加 key 删除最开始的一个
  44. *
  45. * @param key
  46. */
  47. private void cycleKeyList(Object key) {
  48. keyList.addLast(key);
  49. if (keyList.size() > size) {
  50. Object oldestKey = keyList.removeFirst();
  51. delegate.removeObject(oldestKey);
  52. }
  53. }
  54. }

LruCache

  • 存储结构是java.util.LinkedHashMap
  1. /**
  2. * Lru (least recently used) cache decorator.
  3. * LRU 緩存策略 最近最少使用的:移除最长时间不被使用的对象。
  4. *
  5. * @author Clinton Begin
  6. */
  7. public class LruCache implements Cache {
  8. private final Cache delegate;
  9. /**
  10. * {@link LinkedHashMap}
  11. */
  12. private Map<Object, Object> keyMap;
  13. private Object eldestKey;
  14. public LruCache(Cache delegate) {
  15. this.delegate = delegate;
  16. setSize(1024);
  17. }
  18. @Override
  19. public String getId() {
  20. return delegate.getId();
  21. }
  22. @Override
  23. public int getSize() {
  24. return delegate.getSize();
  25. }
  26. /**
  27. * 设置大小
  28. *
  29. * @param size
  30. */
  31. public void setSize(final int size) {
  32. keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
  33. private static final long serialVersionUID = 4267176411845948333L;
  34. @Override
  35. protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
  36. // 数量超出预设值 执行
  37. boolean tooBig = size() > size;
  38. if (tooBig) {
  39. // 获取被移除的key
  40. eldestKey = eldest.getKey();
  41. }
  42. return tooBig;
  43. }
  44. };
  45. }
  46. @Override
  47. public void putObject(Object key, Object value) {
  48. delegate.putObject(key, value);
  49. cycleKeyList(key);
  50. }
  51. @Override
  52. public Object getObject(Object key) {
  53. keyMap.get(key); //touch
  54. return delegate.getObject(key);
  55. }
  56. @Override
  57. public Object removeObject(Object key) {
  58. return delegate.removeObject(key);
  59. }
  60. @Override
  61. public void clear() {
  62. delegate.clear();
  63. keyMap.clear();
  64. }
  65. /**
  66. * 删除最早的一个key
  67. * @param key
  68. */
  69. private void cycleKeyList(Object key) {
  70. keyMap.put(key, key);
  71. if (eldestKey != null) {
  72. delegate.removeObject(eldestKey);
  73. eldestKey = null;
  74. }
  75. }
  76. }