Cache 类主要提供 put/get/remove 方法.
public interface Cache {
/**
* cache 的 id.
*/
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.
* <p>
* Any locking needed by the cache must be provided internally by the cache provider.
*
* @return A ReadWriteLock
*/
default ReadWriteLock getReadWriteLock() {
return null;
}
}
CacheException 和所有的异常类一样.
PerpetualCache 是对 Cache 接口的基本实现,底层使用的是 HashMap.
CacheKey. 缓存在 Cache 中的 key. 换句话说是存放在 Map 中的 key. 为什么会有这种需求了?因为比如说我要缓存某条 sql 对应的结果. 那么一条sql 是否对应着表明、查询条件等,他们合起来作为一个 key 存放在 map 中.
我们再看下 Cache 的装饰模式的实现.
SynchronizedCache:核心方法都加上了 synchronized 关键字.
BlockingCache:阻塞 Cache. 如何理解了?就是 put 的时候随便 put,没有限制,但是获取的时候就有限制了.
首先它会申请获取锁,然后再获取数据,最后释放锁. 如果再次期间,其他线程也来获取数据,将会被阻塞.
如下方法可能造成死锁把?不会. 我们还需要结合 putObject 来看. 使用的锁来完成的.
线程 A 去获取数据,没有获取到,然后阻塞,然后去查询数据库,获得数据,放入缓存,释放锁,这才是一整套流程.
public Object getObject(Object key) {
acquireLock(key);
Object value = delegate.getObject(key);
if (value != null) {
releaseLock(key);
}
return value;
}
public void putObject(Object key, Object value) {
try {
delegate.putObject(key, value);
} finally {
releaseLock(key);
}
}
FifoCache:先进先出 Cache. 该 Cache 实现中,有一个双向队列来记录 key. 容量为 1024. 一旦超过这个容量,则会把最开始的 CacheKey 移除. 遗憾的是不是线程安全的.
LruCache:最近最久为使用 Cache. 它的底层采用一个 HashMap 来记录访问的顺序. 换句话说,LruCache 功能的实现,在于 HashMap.
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;
}
};
}
如下代码就是回收 key. 关于 HashMap 为啥能实现 LRU 的细节,可以参考 HashMap 的源码实现.
private void cycleKeyList(Object key) {
keyMap.put(key, key);
if (eldestKey != null) {
delegate.removeObject(eldestKey);
eldestKey = null;
}
}
ScheduledCache 是一个带定时清除功能的 cache. 默认清理时间是 1 小时.
private final Cache delegate;
protected long clearInterval;
protected long lastClear;
SerializedCache 是一个可以将 value 序列化的 cache. 在 put 的时候自动序列化,在 get 的时候自动的反序列化.
SoftCache 软引用 Cache. 这个比较特殊.
// 最近使用到的会加入其中
private final Deque<Object> hardLinksToAvoidGarbageCollection;
// 软引用队列.
private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
// 代理的 Cache.
private final Cache delegate;
// 翻译成强引用队列的数量.
private int numberOfHardLinks;
public void putObject(Object key, Object value) {
// 移除软引用队列中的元素.
removeGarbageCollectedItems();
delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries));
}
public Object getObject(Object key) {
Object result = null;
@SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache
SoftReference<Object> softReference = (SoftReference<Object>) delegate.getObject(key);
if (softReference != null) {
result = softReference.get();
if (result == null) {
delegate.removeObject(key);
} else {
// See #586 (and #335) modifications need more than a read lock
// 最近使用到的数据会加入到强引用队列中.
synchronized (hardLinksToAvoidGarbageCollection) {
hardLinksToAvoidGarbageCollection.addFirst(result);
if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
hardLinksToAvoidGarbageCollection.removeLast();
}
}
}
}
return result;
}
TransactionalCache:有事务的那么一点意思,也就是说数据不是直接插入到缓存中,而是先放到一个中间地方,等没问题了在提交 到 cache 中.
// 实际缓存存放地址.
private final Cache delegate;
// 字段为true时,则表示当前TransactionalCache不可查询,且提交事务时,会将底层的Cache清空
private boolean clearOnCommit;
private final Map<Object, Object> entriesToAddOnCommit;
// 觉得这个变量作用不大.
private final Set<Object> entriesMissedInCache;
如果 clearOnCommit 为 true,表示不可查询.
public Object getObject(Object key) {
// issue #116
Object object = delegate.getObject(key);
if (object == null) {
entriesMissedInCache.add(key);
}
// issue #146
if (clearOnCommit) {
return null;
} else {
return object;
}
}
// 将数据先放到 entriesToAddOnCommit 集合中.
public void putObject(Object key, Object object) {
entriesToAddOnCommit.put(key, object);
}
commit 核心逻辑.
private void flushPendingEntries() {
for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
delegate.putObject(entry.getKey(), entry.getValue());
}
for (Object entry : entriesMissedInCache) {
if (!entriesToAddOnCommit.containsKey(entry)) {
delegate.putObject(entry, null);
}
}
}
WeakCache 和 SoftCache 实现差不多,不同的是一个是 WeakReference,另一个是 SoftReference.
分享到:
相关推荐
而"mybatis-enhanced-cache-master.zip"则可能是源码包,如果你需要深入了解插件的工作原理或者想要对其进行二次开发,可以解压此文件查看源代码。 在实际使用中,你需要按照以下步骤配置和使用这个插件: 1. 添加...
MyBatis提供了本地缓存(Local Cache)和二级缓存(Second Level Cache)。本地缓存是在SqlSession级别,而二级缓存是在SqlSessionFactory级别,可跨SqlSession共享数据。 9. **事务管理**: MyBatis允许自定义...
Mybatis源码包结构如下: * annotations:注解相关 * binding:mapper相关 * builder:解析xml相关 * cache:缓存 * cursor:返回结果resultset * datasource:数据管理 * exceptions:异常 * executor:执行器 * ...
12. **缓存机制**:MyBatis提供了本地缓存(Local Cache)和二级缓存(Second Level Cache),能有效减少数据库的访问,提高系统性能。 通过对MyBatis 3.5.7源码的深入学习,我们可以了解到其实现细节,包括反射、...
10. **缓存机制**:MyBatis 内置了两级缓存,理解本地缓存(First Level Cache)和二级缓存(Second Level Cache)的工作原理,以及如何自定义缓存。 11. **MyBatis 动态 SQL**:利用 if、choose、when、otherwise...
在深入分析MyBatis 3.4.5源码之前,我们先理解一下框架的核心概念: 1. **SqlSessionFactory**: 是MyBatis的核心,它是一个工厂类,用于创建SqlSession对象。SqlSessionFactory由SqlSessionFactoryBuilder通过读取...
本篇文章将深入分析MyBatis的核心概念和源码结构。 首先,我们来看一下MyBatis的主要组件: 1. **Configuration**:这是MyBatis的核心配置对象,它包含了全局配置信息,如数据源、事务管理器、Mappers等。...
在压缩包文件"**MyBatisCacheTest**"中,可能包含了一个测试用例,用于演示如何在Mybatis中配置和使用缓存,以及如何通过日志分析缓存的效果。通过对这个测试用例的学习和实践,读者可以更直观地理解和掌握Mybatis的...
MyBatis支持本地缓存(Local Cache)和二级缓存(Second Level Cache),提升查询效率。开发者可以根据需求开启和配置缓存。 7. **插件机制** MyBatis允许用户自定义Interceptor插件,对Executor、...
<plugin interceptor="org.format.mybatis.cache.interceptor.ExamplePlugin"> <!-- 可以在这里配置拦截器的参数 --> ``` 此示例配置了一个名为`ExamplePlugin`的拦截器,它将拦截`Executor`接口的`update`...
本文将深入解析MyBatis的核心组件如Configuration、SqlSession等,并针对MyBatis与Spring集成后的缓存管理进行详细分析。 ### MyBatis 概览 MyBatis 是一个优秀的持久层框架,它支持自定义 SQL、存储过程及高级...
Apache Ignite是一款开源的内存数据网格系统,它提供了一个分布式内存计算平台,支持数据库缓存、实时分析以及复杂事件处理等功能。在MyBatis中,二级缓存是提高数据库访问性能的重要手段,它可以将SQL查询结果存储...
#### MyBatis关键组件分析 MyBatis的关键组件主要包括: 1. **configuration.xml**:这是MyBatis的核心配置文件,用于设置各种全局性的配置信息,如连接池配置、缓存配置、事务管理器配置等。 2. **mapper.xml**:...
9. **缓存机制**:MyBatis内置了本地缓存(Local Cache)和二级缓存(Second Level Cache),可以提高数据读取速度,减少数据库访问。 10. **MyBatis与Spring的整合**:在实际项目中,MyBatis常与Spring框架结合...
Mybatis-Plus支持自定义插件,开发者可以根据需求编写插件实现一些特殊功能,如日志记录、性能分析等。 这个`mybatis-plus-ext-3.0.0`版本可能包含了以上特性,并对这些功能进行了优化和升级,以适应不断变化的...
本篇将通过分析“mybatis读缓存源码demo”来探讨这两个缓存层次的工作原理和实现。 一级缓存是 SqlSession 级别的,它是默认开启的。每次执行 CRUD(创建、读取、更新、删除)操作时,MyBatis 都会将结果存储在当前...
在进行 MyBatis 映射之前,首先要对数据模型进行深入分析: - **明确每张表存储的信息**。 - **明确每张表中关键字段**:主键、外键、非空字段。 - **明确数据库中表与表之间的外键关系**。 - **明确业务中表与表的...
- 缓存机制:结合Spring的Cache抽象,可以实现缓存功能,提高系统性能。 - 安全框架集成:如Spring Security,提供认证和授权功能,增强系统的安全性。 在"yiteDesign"这个压缩包中,可能包含了整合SSM框架的相关...
至于"工具"标签,可能是指使用一些辅助工具来管理和查看MyBatis的缓存,比如通过日志监控、性能分析工具等,这些可以帮助我们更好地理解和调整缓存的性能。 在文件列表"mybatis-04"中,可能包含了MyBatis的配置文件...