在前面的内容中已经分析了Executor的三个实现类SimpleExecutor、ReuseExecutor和BatchExecutor。这里开始分析Executor接口的装饰器类CachingExecutor。
CachingExecutor类直接实现了Excutor接口,是装饰器类,主要用来增强缓存相关功能。在CachingExecutor类中,为了完成缓存相关功能,需要TransactionalCacheManager和TransactionalCache两个类的支持,其中TransactionalCacheManager类主要用来管理缓存数据的对象TransactionalCache,而TransactionalCache对象是用来真正缓存数据的对象。
/**
* 真正用来操作数据库操作的 Executor对象
*/
private final Executor delegate;
/**
* 用于管理缓存的TransactionalCacheManager对象
*/
private final TransactionalCacheManager tcm = new TransactionalCacheManager();
public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}
在CachingExecutor类中,事务、关闭对象相关方法都是通过真正的Executor对象实例delegate和TransactionalCacheManager 实例tcm配合完成,比较简单,这里不再具体分析。示例如下:
@Override
public void commit(boolean required) throws SQLException {
delegate.commit(required);
tcm.commit();
}
@Override
public void rollback(boolean required) throws SQLException {
try {
delegate.rollback(required);
} finally {
if (required) {
tcm.rollback();
}
}
}
@Override
public void close(boolean forceRollback) {
try {
//issues #499, #524 and #573
if (forceRollback) {
tcm.rollback();
} else {
tcm.commit();
}
} finally {
delegate.close(forceRollback);
}
}
@Override
public boolean isClosed() {
return delegate.isClosed();
}
该方法中,首先通过flushCacheIfRequired()方法清理缓存,然后再调用真正的Executor对象的update()方法,执行update操作。
@Override
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}
通update()方法类似。
@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
flushCacheIfRequired(ms);
return delegate.queryCursor(ms, parameter, rowBounds);
}
在CachingExecutor类中,真正受影响的其实就是query()方法。逻辑如下:
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
throw new ExecutorException("Caching stored procedures with OUT params is not supported. Please configure useCache=false in " + ms.getId() + " statement.");
}
}
}
}
用于保存在事务中需要向某个二级缓存中添加的缓存数据。nsactionalCache类各个方法的作用,详见方法的注释,没有复杂逻辑,不再具体分析。
public class TransactionalCache implements Cache {
private static final Log log = LogFactory.getLog(TransactionalCache.class);
//底层封装的二级缓存所对应的 Cache对象
private final Cache delegate;
//当该字段为true时,则表示当前 TransactionalCache不可查询, 且提交事务时会将底层Cache清空
private boolean clearOnCommit;
//暂时记录添加到TransactionalCache中的数据 在事务提交时,会将其中的数据添加到二级缓存中
private final Map<Object, Object> entriesToAddOnCommit;
//记录缓存未命中CacheKey对象
private final Set<Object> entriesMissedInCache;
public TransactionalCache(Cache delegate) {
this.delegate = delegate;
this.clearOnCommit = false;
this.entriesToAddOnCommit = new HashMap<Object, Object>();
this.entriesMissedInCache = new HashSet<Object>();
}
@Override
public String getId() {
return delegate.getId();
}
@Override
public int getSize() {
return delegate.getSize();
}
/**
* 首先会查询底层的二级缓存,并将未命中的key记录到entriesMissedInCache中,
* 之后会根据clearOnCommit字段的值决定具体的返回值
*/
@Override
public Object getObject(Object key) {
// issue #116
Object object = delegate.getObject(key);
if (object == null) {
entriesMissedInCache.add(key);
}
// issue #146
//如果clearOnCommit为true ,则当前TransactionalCache不可查询,始终返回 null
if (clearOnCommit) {
return null;
} else {
return object;
}
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
/**
* 该方法并没有直接将结果对象记录到其封装二级缓存中,
* 而是暂时保存在 entriesToAddOnCommit集合中,
* 在事务提交时才会将这些结果对象从entriesToAddOnCommit集合添加到二级缓存中。
*/
@Override
public void putObject(Object key, Object object) {
entriesToAddOnCommit.put(key, object);
}
@Override
public Object removeObject(Object key) {
return null;
}
/**
* 该方法会清空entriesToAddOnCommit集合,并设置 clearOnCommit为true
*/
@Override
public void clear() {
clearOnCommit = true;
entriesToAddOnCommit.clear();
}
/**
* 根据clearOnCommit字段的值决定是否清空二级缓存,
* 然后调用flushPendingEntries()方法将 entriesToAddOnCommit集合中记录的结果对象保存到缓存中
*/
public void commit() {
if (clearOnCommit) {
delegate.clear();
}
//将entriesToAddOnCommit集合中的数据保存到二级缓存
flushPendingEntries();
reset();
}
/**
* 将entriesMissedlnCache集合中记录的缓存项从二级缓存中删除,
* 并清空entriesToAddOnCommit集合和entriesMissedlnCache集合
*/
public void rollback() {
unlockMissedEntries();
reset();
}
/**
* 重置clearOnCommit == false ,并清空entriesToAddOnCommit和entriesMissedInCache集合
*/
private void reset() {
clearOnCommit = false;
entriesToAddOnCommit.clear();
entriesMissedInCache.clear();
}
/**
* 保持数据到二级缓存中
*/
private void flushPendingEntries() {
//遍历entriesToAddOnCommit集合,将其中记录的缓存项添加到二级缓存中
for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
delegate.putObject(entry.getKey(), entry.getValue());
}
//将仍未命中的的缓存项,把value设置为null,存入二级缓存中
for (Object entry : entriesMissedInCache) {
if (!entriesToAddOnCommit.containsKey(entry)) {
delegate.putObject(entry, null);
}
}
}
/**
* 将entriesMissedlnCache集合中记录的缓存项从二级缓存中删除
*/
private void unlockMissedEntries() {
for (Object entry : entriesMissedInCache) {
try {
delegate.removeObject(entry);
} catch (Exception e) {
log.warn("Unexpected exception while notifiying a rollback to the cache adapter."
+ "Consider upgrading your cache adapter to the latest version. Cause: " + e);
}
}
}
}
用于管理 CachingExecutor中使用的二级缓存对象TransactionalCache。该类中的方法基本上都是基于缓存Cache接口的实现,不再具体分析。
public class TransactionalCacheManager {
/**
* 其中的key,对应的CachingExecutor中使用的 二级缓存对象,
* value,对应的TransactionalCache对象,
* 在该TransactionalCache中封装了对应二级缓存对象,也就是这里的 key
*/
private final Map<Cache, TransactionalCache> transactionalCaches = new HashMap<Cache, TransactionalCache>();
public void clear(Cache cache) {
getTransactionalCache(cache).clear();
}
public Object getObject(Cache cache, CacheKey key) {
return getTransactionalCache(cache).getObject(key);
}
public void putObject(Cache cache, CacheKey key, Object value) {
getTransactionalCache(cache).putObject(key, value);
}
public void commit() {
for (TransactionalCache txCache : transactionalCaches.values()) {
txCache.commit();
}
}
public void rollback() {
for (TransactionalCache txCache : transactionalCaches.values()) {
txCache.rollback();
}
}
private TransactionalCache getTransactionalCache(Cache cache) {
TransactionalCache txCache = transactionalCaches.get(cache);
if (txCache == null) {
txCache = new TransactionalCache(cache);
transactionalCaches.put(cache, txCache);
}
return txCache;
}
}