一.spring cache

Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,

而是直接从缓存中获取结果进行返回。所以在使用Spring   Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。使用Spring Cache需要我们做两方面的事:

1.声明某些方法使用缓存

2.配置Spring对Cache的支持

Spring为我们提供了几个注解来支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable标记的方法在执行后Spring Cache将缓存其返回结果,而使用@CacheEvict标记的方法

会在方法执行前或者执行后移除Spring Cache中的某些元素。这里只介绍几个常用的属性。

基于注解的相关概念:

1.@Cacheable 
    可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,

Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,

值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略。

需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。@Cacheable可以指定三个属性,value、key和condition。

2.@CachePut
    在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,

否则才会执行并将返回结果存入指定的缓存中。而@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,

而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。

3.@CacheEvict
    @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。

其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。
 
属性一 :value

必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称,为ehcache.xml中的<cache name="myCache"/> 。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

属性二 :key

缓存的Key,当我们没有指定该属性时,Spring将使用默认策略生成key(表示使用方法的参数类型及参数值作为key),key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。

我们还可以自定义策略:自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”

key的生成策略有两种:一种是默认策略,一种是自定义策略
       ¹默认的key生成策略是通过KeyGenerator生成的,其默认策略如下:
            1.如果方法没有参数,则使用0作为key。
            2.如果只有一个参数的话则使用该参数作为key。
            3.如果参数多余一个的话则使用所有参数的hashCode作为key
        ²自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index

属性三 :condition

有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。
condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。

如下示例表示只有当user的id为偶数时才会进行缓存
              @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
              public User find(User user) {
                  System.out.println("find user by user " + user);
                  return user;
              }

属性四 :allEntries

是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。
              @CacheEvict(value="users", allEntries=true)
              public void delete(Integer id) {
                 System.out.println("delete user by id: " + id);
              }

属性五 :beforeInvocation

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
             @CacheEvict(value="users", beforeInvocation=true)
             public void delete(Integer id) {
               System.out.println("delete user by id: " + id);
             }

注意我们也可以使用ehcache的去除策略最近使用(LRU)"策略,其它还有先入先出FIFO,最少使用LFU,较少使用LRU

基于注解配置:

配置Spring对基于注解的Cache的支持,首先我们需要在Spring的配置文件中引入cache命名空间,其次通过<cache:annotation-driven />就可以启用Spring对基于注解的Cache的支持。

<cache:annotation-driven/>有一个mode属性,可选值有proxy和aspectj。默认是使用proxy。当mode为proxy时,只有缓存方法在外部被调用的时候Spring Cache才会发生作用,

这也就意味着如果一个缓存方法在其声明对象内部被调用时Spring Cache是不会发生作用的。而mode为aspectj时就不会有这种问题。另外使用proxy时,只有public方法上的@Cacheable等标注才会起作用,

如果需要非public方法上的方法也可以使用Spring Cache时把mode设置为aspectj。此外,<cache:annotation-driven/>还可以指定一个proxy-target-class属性,表示是否要代理class,默认为false。

我们前面提到的@Cacheable、@cacheEvict等也可以标注在接口上,这对于基于接口的代理来说是没有什么问题的,但是需要注意的是当我们设置proxy-target-class为true或者mode为aspectj时,是直接基于class进行操作的,

定义在接口上的@Cacheable等Cache注解不会被识别到,那对应的Spring Cache也不会起作用了。

需要注意的是<cache:annotation-driven/>只会去寻找定义在同一个ApplicationContext下的@Cacheable等缓存注解。

基于XML配置:

   <cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="users">
<cache:cacheable method="findById" key="#p0"/>
<cache:cacheable method="find" key="#user.id"/>
<cache:cache-evict method="deleteAll" all-entries="true"/>
</cache:caching>
</cache:advice>
上面配置定义了一个名为cacheAdvice的cache:advice,其中指定了将缓存findById方法和find方法到名为users的缓存中。这里的方法还可以使用通配符“*”,比如“find*”表示任何以“find”开始的方法。
 
有了cache:advice之后,我们还需要引入aop命名空间,然后通过aop:config指定定义好的cacheAdvice要应用在哪些pointcut上。如:
 
    <aop:config proxy-target-class="false">
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.xxx.UserService.*(..))"/>
</aop:config>

二.EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点。

ehcache官网:http://www.ehcache.org/  可以下载文档看看,里面写的很清楚。

主要的特性有:
1. 快速
2. 简单
3. 多种缓存策略
4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
5. 缓存数据会在虚拟机重启的过程中写入磁盘
6. 可以通过RMI、可插入API等方式进行分布式缓存
7. 具有缓存和缓存管理器的侦听接口
8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
9. 提供Hibernate的缓存实现
 
ehcache.xml:里面的注释写的很清楚了。
<diskStore>   : 当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口)  
<diskStore path="">     : 用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index  
name : "缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里)  
maxElementsInMemory  : 缓存最大个数。

eternal="false"  : 对象是否永久有效,一但设置了,timeout将不起作用。 (必须设置)
maxEntriesLocalHeap="1000"  : 堆内存中最大缓存对象数,0没有限制(必须设置)
maxEntriesLocalDisk= "1000"   : 硬盘最大缓存个数。
overflowToDisk="false"   : 当缓存达到maxElementsInMemory值是,是否允许溢出到磁盘(必须设置)(内存不足时,是否启用磁盘缓存。)

diskSpoolBufferSizeMB  : 这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskPersistent="false"  : 磁盘缓存在JVM重新启动时是否保持(默认为false)
timeToIdleSeconds="0"  : 导致元素过期的访问间隔(秒为单位),即当缓存闲置n秒后销毁。 当eternal为false时,这个属性才有效,0表示可以永远空闲,默认为0
timeToLiveSeconds="600"   : 元素在缓存里存在的时间(秒为单位),即当缓存存活n秒后销毁. 0 表示永远存在不过期

memoryStoreEvictionPolicy="LFU" : 当达到maxElementsInMemory时,如何强制进行驱逐默认使用"最近使用(LRU)"策略,其它还有先入先出FIFO,最少使用LFU,较少使用LRU
diskExpiryThreadIntervalSeconds :磁盘失效线程运行时间间隔,默认是120秒。
clearOnFlush   : 内存数量最大时是否清除。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true" monitoring="autodetect"
dynamicConfig="true"> <diskStore path="java.io.tmpdir"/>
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskSpoolBufferSizeMB="30"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache> <cache name="myCache"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="30"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap"/>
</cache> </ehcache>

 
 

使用spring cache和ehcache的更多相关文章

  1. 使用spring cache和ehcache之前必须了解的

    好长时间没写博客了,真的是没时间啊.ps:其实就是懒!!接下来几篇要写下缓存,这里主要写下ehcache与spring整合的内容,包括aop形式的缓存,基于注解的缓存,页面缓存这三方面吧.在这之前先要 ...

  2. SpringBoot系列:Spring Boot集成Spring Cache,使用EhCache

    前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...

  3. 在Spring中使用cache(EhCache的对象缓存和页面缓存)

    Spring框架从version3.1开始支持cache,并在version4.1版本中对cache功能进行了增强. spring cache 的关键原理就是 spring AOP,通过 spring ...

  4. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

  5. Spring cache简单使用guava cache

    Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...

  6. 注释驱动的 Spring cache 缓存介绍

    概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...

  7. [转]注释驱动的 Spring cache 缓存介绍

    原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ 概述 Spring 3.1 引入了激动人心的基于注释(an ...

  8. Spring Cache 介绍

    Spring Cache 缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 c ...

  9. 注释驱动的 Spring cache 缓存介绍--转载

    概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...

随机推荐

  1. 基于Neutron的Kubernetes SDN实践经验之谈

    首先,向大家科普下Kubernetes所选择的CNI网络接口,简单介绍下网络实现的背景. CNI即Container Network Interface,是一套容器网络的定义规范,包括方法规范.参数规 ...

  2. Python更新库

    查看系统里过期的python库,可以用pip命令 [root@vnode33 sim-enb-sgi]# pip list #列出所有安装的库 Package Version ------------ ...

  3. 一个基于NodeJS开发的APP管理CMS系统

    花了大概3周独立开发了一个基于NodeJS的CMS系统,用于公司APP的内容管理( **公司APP?广告放在最后 ^_^ ** ,管理员请理解~~~ )晚上看了部电影还不想睡,闲着也是闲着就作下小小总 ...

  4. 实践lnmpde 的安装

    1.先安装apache, yum install httpd 2.安装MySQL rpm -qa | grep mysql       // 这个命令就会查看该操作系统上是否已经安装了mysql数据库 ...

  5. Node.js中exports,module.exports以及require方法

    在Node.js中,使用module.exports.f = ...与使用exports.f = ...是一样的,此时exports就是module.exports的一种简写方式.但是,需要注意的是, ...

  6. SpringMvc跨域支持

    SpringMvc跨域支持 在controller层加上注解@CrossOrigin可以实现跨域 该注解有两个参数 1,origins  : 允许可访问的域列表 2,maxAge:飞行前响应的缓存持续 ...

  7. TeamWork#3,Week5,Scrum Meeting 11.15

    经过最近一段时间的努力,我们调整了爬虫结构,并在继续进行爬虫开发,马上可以进行新爬虫与服务器连接的测试. 成员 已完成 待完成 彭林江 基本完成爬虫结构调整 新爬虫与服务器连接 郝倩 基本完成爬虫结构 ...

  8. TeamWork#1,Week 2,Learn In Team

    我觉得做为一个团队,每个人的能力固然重要,但是更重要的是几个人能同心协力. 俗话说“三个臭皮匠,赛过诸葛亮”,团队合作往往能激发出团体不可思议的潜力,集体协作干出的成果往往能超过成员个人业绩的总和.在 ...

  9. 第10章 系统级I/O(下)

    10.7  I/O重定向 Unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输出输入联系起来. 例如:unix>ls>foo.txt,使得外壳加载和执行ls程序,将标准输出重定 ...

  10. 冲刺One之站立会议3 /2015-5-16

    2015-5-16 今天我们主要完成一部分服务器端的内容,因为只有服务器端完成了主要功能其他的部分才可以测试有没有成功实现目标.具体包括服务器登陆时需要的端口号.启动时间.服务器状态的显示.在线人数等 ...