mybatis用到的任何的缓存都需要使用 org.apache.ibatis.cache.Cache 接口, 包括第三方的缓存,如果想要集成到Mybatis里面也需要实现org.apache.ibatis.cache.Cache接口.

Mybatis只有一个cache实现类是org.apache.ibatis.cache.impl.PerpetualCache ,在mybatis里面,无论是一级缓存还是二级缓存用的都是PerpetualCache来实现的.内部是通过HashMap来实现的.
除了默认的实现类之外还有org.apache.ibatis.cache.decorators包下的对cache功能的装饰器,(用的装饰者设计模式), 这些装饰器是为了增强缓存的功能.比如说ScheduledCache是有定时清理的功能的.LoggingCache是可以实现日志记录的.

具体装饰者效果可以在org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)方法内部的cache 打断点就能看到 cache被装饰者层层包装了..


(一)cache对象创建时机

1.一级缓存


一级缓存被放在BaseExecutor的成员变量上, 每创建一个Executor执行器就会有一个对应的一级缓存.一级缓存不用做任何配置,默认就是打开状态.



2.二级缓存


二级缓存在一级缓存之前工作.因为二级缓存比一级缓存的作用域更广,二级缓存是包围在一级缓存之外的,肯定是先走二级缓存.

如果要实现更广的作用范围,二级缓存放在一级缓存的装饰器里面了,这个装饰器是CachingExecutor. 开启二级缓存配置之后CachingExecutor会对BaseExecutor进行一次包装.
二级缓存管理缓存是用org.apache.ibatis.cache.TransactionalCacheManager

二级缓存是需要在mybatis-config.xml那里进行配置的.如果打开的话,默认是全局缓存的,还需要在mapper.xml里面配置一下,说明这个mapper对应的nameSpace需要开启二级缓存.

缓存源码简单流程分析 - 图1

应用在访问数据库的时候会先去CachingExecutor里面查找有没有二级缓存,如果有的话,直接获取并返回给应用,如果没有的话才会去一级缓存里面查找,如果一级缓存也没有的话,就会直接从数据库里面查询.