以下内容是根据JSR107-Java-Caching-API,加上平时的使用总结的。
注:建议在读下面的内容之前,先去了解下JSR107中的内容,trust me!
对上图的说明:一个Application可以使用多个CachingProvider;每个CachingProvider可以管理多个CacheManager;每个CacheManager可以管理多个Cache;每个Cache中可以有多个Entry。在Spring中使用这个Ehcache时,就需要定义CacheManager的name和CacheManager中管理的Cache。
Entry存储在Cache中时,有俩种机制: Store-By-Value和Store-By-Reference。
实际使用时是Reference还Value类型,可自行写几行代码验证下,本人验证了下,在不配置特殊参数的情况是Reference类型。
由于JSR107只是规范,而实际的每个厂商底层实现的不同,加上可能写到磁盘或者Ehcache集群(Entry要在网络中传输),所以Entry中的key和value最好都实现java.io.Serializable。
如下是ehcache配置文件,暂且将该文件命名为ehcache.xml(后面说明中要用到)。
<?xml version="1.0"?>
<ehcache xmlms:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="java.io.tmpdir" />
<cache name="userCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="0" timeToLiveSeconds="10" overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
</ehcache>
Spring中使用ehcache.xml如下图所示,由EhcacheManagerFactoryBean源码可知,这个ehcache.xml被用于创建一个CacheManager。Spring容器中userCacheManager对应的bean是一个CacheManager(如果觉得困惑,那么先去了解下org.springframework.beans.factory.FactoryBean的作用——Mybatis的SqlSessionFactoryBean也使用了FactoryBean的功能,而后再去看下EhCacheManagerFactoryBean的源码)。
<bean id="userCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
<property name="cacheManagerName" value="userCacheManager"/>
</bean>
至此我们就有了一个name为userCacheManager的CacheManager,之后就可以使用name为userCache的Cache了。
这种xml配置一般都有一个schema用于约束xml节点或节点属性的值以及类型。所以可以先去看下ehcache官方给出的ehcache.xsd,Spring中用于配置bean的xml也有它自己的schema,而且Spring的xsd在细节、注释上比ehcache的好。
下图上框中ref的值是ehcache节点中允许的元素种类;下框中name的值是ehcache节点的属性name。比如从下图中可以看出ehcache节点中可以出现0个或多个cache元素;但是diskStore只能出现0个或者1个;ehcache的属性updateCheck的默认值是true。
配置很多,这里就不细细列出了,建议去查看下官方的ehcache.xsd。
最近在看Ehcache的实现,发现其底层用到了LinkedHashmap、ConcurrentHashmap,且在此基础之上做了一定的个性化,但是如何做到element的searchable、写到disk等是如何实现,目前还没看到。待后续努力。
在此,建议开发人员多去了解下JCP的规范,对了解框架有很大的帮助,比如
同样,我们在设计框架时,应该注重规范化,参考JCP的相应规范,比如Spring batch模块就遵循了batch规范,这样框架才会易于学习、传播。
(adsbygoogle = window.adsbygoogle || []).push({});