废话不说,今天花了一个下午的时间, 专门啃Hibernate的二级缓存部分. Hibernate要支持好几种缓存, 那么它肯定封装了各种不同的缓存策略, 根据不同的缓存产品(如EHCache,Jboss Cache)相应处理.
我手上的源码版本是Hibernate-3.3.1GA, 按照org.hibernate.cache包里面的说明文件package.html的说明, 这个版本相比以前, 已经不再使用org.hibernate.cache.Cache/CacheProvider接口, 转而使用了org.hibernate.cache.Region/RegionFactory接口, 并且每个Region独立创建自己对缓存的访问策略. (Hibernate为每个实体类创建一个Region作为缓存区, 默认情况下使用类的全路径名做为这个Region的名称)
我个人认为, 看代码应该要带着自己的问题去跟踪, 这样才能做到线索清晰, 目的明确. Hibernate的二级缓存有实体类的缓存和集合的缓存, 下面以实体类的缓存为例, 跟踪Hibernate的二级缓存处理过程.
* 问题1 , 既然Hibernate使用二级缓存, 那么他的二级缓存是什么时候创建的?
答案很简单, 是在SessionFactoryImpl实例化的时候创建的. org.hibernate.cache.RegionFactory有个方法 public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException; 顾名思义, 是用来创建缓存区的, 跟踪一下什么方法调用的就行.
从SessionFactoryImpl 244行开始有一段:
我最初的想法是认为Hibernate在我们使用到某个类的时候(比如通过session.load(class,id)方法)才会创建缓存区并且 加载缓存对象, 这样可能更符合"懒"加载的特性. 这里我不是很明白为什么Hibernate提前初始化了这些缓存区. 不过, 实际情况中, 很多的应用都是在一开始就加载业务数据缓存, 比如角色定义, 规则, 模板等等的对象. 相对这些操作而言, Hibernate创建缓存区并不算大的开销.(我见过某些系统初始加载耗时半个钟)
* 问题二 , Hibernate创建缓存区的时候, 里面发生了什么事情?
Hibernate的作者说"创建SessionFactory的代价非常昂贵, 而创建Session的代价很低". 此话至少前半句不假. 看上面的代码, 就知道实例化的时候创建缓存区和对应的访问策略, 如果实体类超过100个, 就要创建100个缓存区和策略, 相比创建一个Session, 确实就有些耗费不起. 我们跟踪到settings.getRegionFactory().buildEntityRegion(..)方法内部看看发生了什么.
1) buildEntityRegion() 方法
org.hibernate.cache.RegionFactory是一个接口, 它的实现