这篇文章是根据谷歌翻译大致修改出来的,由于原文不知道是什么语,所以可能导致翻译的有错误和不准确的地方,但是大致的方向感觉还是蛮不错的,所以在这里整理了一下,希望能够有所帮助。
高速缓存一直是一个非常需要这两个提高应用程序性能并降低其工作量。此外,它的用处今天是特别明显,可以作出处理成千上万的游客concurrents.D'un架构上的Web应用,高速缓存管理正交于应用程序的业务逻辑和出于这个原因,应该对应用程序本身的发展产生的影响最小。从3.1版本开始,Spring提供了高速缓存管理的API,类似声明式事务管理。缓存的抽象接口,统一使用不同的缓存解决方案,对代码的影响最小。
spring用Java方法,对带有参数的组合第一次请求到一个方法,spring将返回值存储在高速缓存中。因此,下一个请求将是直接使用从高速缓存的值,而不必调用可能的高代价的方法。一切都透明地施加,而不会影响调用的方法。
在这篇文章中,我们将看到与Spring的两个不同的缓存存储的实现。
- Java的ConcurrentHashMap
- Ehcache
实现
spring和缓存的整合是简单透明的,通过@Cacheable注解标注需要缓存的方法
1
2
|
@Cacheable (value= "dataCache" )
public Reponse getDatas(Long param1, String param2){ }
|
dataCache是相关联的高速缓存的名称。第一次调用这个方法的时候,该方法执行并将执行的结果存入以<参数1,参数2>哈希出来的秘钥为结果的结果集中去,当使用同样的参数再次调用的时候,这个方法不需要再次的执行。
有可能多于一个的缓存关联到我们的方法
1
2
|
@Cacheable ({ "dataCache" ,” default ”})
public Reponse getDatas(Long param1, String param2){ }
|
在这种情况下,每个缓存都会在方法执行之前检查,如果有命中的话,则相关的值会被返回。
生成缓存键
一个缓存管理器的基本算法的占比比较小。缓存可以看做是一个存储器区域,在其中存储的对象个由唯一的秘钥进行映射。对象搜索的过程如下:
1、计算key(利用hash方法得到hashcode)
2、根据key值查找对象
3、如果找到对象返回该结果
4、如果找不到,则会计算实际与对象相关连的key,并把对象存入相应的位置
spring使用的是简单的哈希,它根据传递的方法参数生成key
自定义缓存
目标方法不能简单的根据参数产生不用的key,根据参数生成的仅仅是一些简单的情况
1
2
|
@Cacheable (value= "dataCache" )
public Reponse getDatas(Long param1, String param2, boolean param3){ }
|
@Cacheable是允许开发人员自己指定key生成的方式的,可以使用spel表达式来做这件事情
1
2
|
@Cacheable (value= "dataCache" , key= "#param2" )
public Reponse getDatas(Long param1, String param2, boolean param3){ }
|
上边的这种情况,缓存计算的秘钥的参数就仅仅是Parma2
spring也允许使用嵌套的属性
1
2
|
@Cacheable (value= "dataCache" , key=#param2.name")
public Reponse getDatas(Long param1, Data param2, boolean param3){}
|
这种情况就是根据Parma2的name属性计算的秘钥
条件缓存
有一个缓存可能不适用于所用情况下的缓存,但是在某一些情况下需要缓存,缓存的时候根据SPEL表达式计算的真假来进行缓存的处理,如果条件为真的情况下则进行缓存
1
2
|
@Cacheable (value= "dataCache" , key= "#param2" , condition= "#param2.length<64" )
public Reponse getDatas(Long param1, String param2, boolean param3){ }
|
在这种情况下是仅仅当第二个参数的长度小于64的时候才会进行缓存
@CacheEvict注解
spring的缓存不仅仅可以将数据进行缓存还可以清除缓存一个缓存存储。该过程用于去除过时的数据或不用的缓存数据。注解@ CacheEvict定义了执行缓存清空的方法,这些是删除缓存中数据的触发器。
1
2
|
@CacheEvict (value= "dataCache" )
public void reloadData(){ }
|
这个选项是非常有必要的,当一个缓存的数据的需要清空的时候就会用到这个方法。
启用缓存
要启用一个spring项目对缓存的支持,我们需要再命名空间上增加对缓存注释的语句
1
2
3
4
5
6
7
8
9
10
11
|
< beans xmlns = "http://www.springframework.org/schema/beans" xmlns:cache = "http://www.springframework.org/schema/cache" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:context = "http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/context">
< cache:annotation-driven />
|
删除注解可以禁用缓存,也可在我们的配置类中启用对缓存的使用
1
2
3
|
@Configuration @EnableCaching public class AppConfig { }
|
技术限制
对象传递方法的参数必须有自己的hashcode方法,以便用来计算秘钥
作为参数传递和返回的对象,它应该是可以序列化的
实现选择
spring提供了两种基本的实现:
- java的concurrentHashMap
- Ehcache
使用它们的时候,只需要声明适当的CacheManger和管理器的实体
使用java的ConcurrentHashMap
1
2
3
4
5
6
7
8
|
< bean id = "cacheManager" class = "org.springframework.cache.support.SimpleCacheManager" >
< span style = "white-space:pre" > </ span >< property name = "caches" >
< span style = "white-space:pre" > </ span >< set >
< span style = "white-space:pre" > </ span >< bean class = "org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name = "default" />
< span style = "white-space:pre" > </ span >< bean class = "org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name = "dataCache" />
< span style = "white-space:pre" > </ span ></ set >
< span style = "white-space:pre" > </ span ></ property >
</ bean >
|
每个Manger都需要一个名称,通过注释来识别它。人们可以由一个Manger管理多个SimpleCacheManger,这个实现很基本不需要而外的库。
实现Ehcache
声明CacheManger
1
2
3
4
5
6
7
8
9
|
bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager">
< property name = "cacheManager" ref = "ehcache" />
</ bean >
< bean id = "ehcache" class = "org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
< property name = "configLocation" value = "classpath:ehcache.xml" />
< property name = "shared" value = "true" />
</ bean >
|
在ehcache.xml中文件是应用程序缓存参数文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<ehcache xsi:noNamespaceSchemaLocation= "ehcache.xsd" updateCheck= "true" monitoring= "autodetect" dynamicConfig= "true" maxBytesLocalHeap= "150M" >
<diskStore path= "java.io.tmpdir" />
<defaultCache eternal= "false"
maxElementsInMemory= "100" overflowToDisk= "false" />
<cache name= "dataCache"
eternal= "false"
timeToIdleSeconds= "300"
maxBytesLocalHeap= "30M"
timeToLiveSeconds= "300"
overflowToDisk= "true"
diskPersistent= "false"
diskExpiryThreadIntervalSeconds= "120"
memoryStoreEvictionPolicy= "LRU" />
</ehcache>
|
使用ehcache的,我们可以在一个非常简单的方式定义多个高速缓存不同的参数
名称:高速缓存的标识符
maxBytesLocalHeap:定义高速缓存可以使用虚拟机的字节数。如果一个的CacheManager maxBytesLocalHeap已经设置,则高速缓存的所确定的尺寸将被减去的CacheManager。其他缓存共享的休息。此属性的值是数据<编号> K | K | M | M | G | G代表千字节(K | K),兆字节(M | M)或千兆字节(G | G)。
永恒:定义元素是否是永恒的。如果是这样的情况下,超时将被忽略,该项目是永不过期。
timeToIdleSeconds:这是秒数,该项目自从他上次utilisation.La默认值为0住,元素保持静止
timeToLiveSeconds:这是秒数该项目已住自cache.La默认价值创造为0,该项目将永远活着。
memoryStoreEvictionPolicy掠夺政策:LRU - 最近最少使用,不经常使用的FIFO -先入先出,按创建日期最古老的元素。
diskExpiryThreadIntervalSeconds:的止赎过程控制两个运行之间的秒数。
diskPersistent:允许存储在磁盘上的虚拟机的两场比赛间的对象恢复对象。
overflowToDisk:确定对象是否可以被存储在磁盘上的情况下达到最大的存储元件的
总结用一个简单的数学公式:expirationTime = Math.min((creationTime + timeToLive),(mostRecentTime + timeToIdle))
总结
以上就是本文关于spring缓存代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/maoyeqiu/article/details/50433934