一、启用对缓存的支持

  Spring 对缓存的支持最简单的方式就是在方法上添加@Cacheable和@CacheEvict注解,

  再添加注解之前,必须先启用spring对注解驱动的支持,基于java的配置的话,直接在某个java配置类上添加@EnableCaching。

  如下:

 @Configuration
//启用缓存
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(){
// 配置缓存管理器
return new ConcurrentMapCacheManager();
}
}
@EnableCaching会创建一个切面,并触发spring缓存注解的切点。

二、缓存管理器

 在上面的代码中除了启用缓存支持外,还声明了一个缓存管理器,缓存管理器是spring缓存抽象的核心,能与多个流行的缓存实现集成。
 spring提供了一些缓存管理器,主要有以下几个:
  • SimpleCacheManager
  • NoOpCacheManager
  • ConCurrentMapCacheManager
  • CompositeCacheManager
  • EnCacheCacheManager
  • RedisCacheManager
  • GemfireCacheManager

三、使用Ehcache

  引入依赖:

        <dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.3</version>
</dependency>

  java配置如下:

    @Bean
public EhCacheCacheManager ehCacheCacheManager(CacheManager cacheManager){
return new EhCacheCacheManager(cacheManager);
} @Bean
public EhCacheManagerFactoryBean ehCache(){
EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
bean.setConfigLocation(new ClassPathResource("ehcache.xml"));
     return bean;
  }

  需要注意的是,因为spring和ehcache都定义了CacheManager类型,为了将ehcache的CacheManager注入到spring的EhCacheCacheManager中,spring提供了EhCacheManagerFactoryBean来生成EhCache的CacheManager

  除了在spring中配置bean以外,还需要针对对ehcache的配置,ehcache配置采用XML,一个简单的配置如下,指明了最大堆大小为50M,存活时间为200s,  

<?xml version="1.0" encoding="utf-8" ?>
<ehcache>
<cache name="simpleCache"
maxBytesLocalHeap="50m"
timeToLiveSeconds="200"/>
</ehcache>

当然这只是一个很简单的版本,有关ehcache的详细使用方法见ehcache官网

四、使用redis缓存

   spring data redis提供了RedisCacheManager,RedisCacheManager会通过RedisTemplate与redis服务器进行协作,将缓存条目存储到redis中。

   为了使用RedisCacheManager需要RedisTemplate Bean以及RedisConnectionFactory实现类的bean,关于如何配置RedisTemplate,戳这

   RedisCacheManager的java配置如下:

   @Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory){
return RedisCacheManager.create(connectionFactory);
}

五、使用多个缓存管理器

  可以CompositeCacheManager来聚合多个cacheManager,它会迭代这些缓存管理器,查找之前的缓存的值。

  CompositeCacheManager通过一个或多个缓存管理器来进行配置,如下,同时配置了RedisCacheManager和EhCacheCacheManager 

@EnableCaching
@Configuration
public class Config { @Bean
public EhCacheManagerFactoryBean ehCache(){
EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
bean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return bean;
} @Bean
public CacheManager cacheManager(net.sf.ehcache.CacheManager cacheManager,
RedisConnectionFactory factory){
CompositeCacheManager compositeCacheManager = new CompositeCacheManager();
List<CacheManager> cacheManagerList = new ArrayList<>();
cacheManagerList.add(new EhCacheCacheManager(cacheManager));
cacheManagerList.add(RedisCacheManager.create(factory));
compositeCacheManager.setCacheManagers(cacheManagerList);
return compositeCacheManager;
}
}

六、声明式注解缓存

  对于缓存声明,Spring的缓存提供了一组Java注释:

  • @Cacheable:用于缓存数据.spring在方法调用之前,首先会在缓存中查找方法的返回值,如果找到,直接返回缓存的值,否则执行方法,将返回的结果会被放到缓存中。

  • @CacheEvict:移除缓存。spring会在缓存中移除一个活多个值。

  • @CachePut:用于更新缓存。将方法执行的返回值放到缓存中,在方法调用前并不会检查缓存。

  • @Caching:用于组合一组缓存注解。组合一系列缓存注解以便同时使用。

  • @CacheConfig:在类级别设置一些常见的缓存设置。

  1、@Cacheable与@CachePut

    方法级注解,将方法的返回值缓存起来,在下次使用相同参数时会使用缓存中的数据而不必执行该方法,最简的形式如下:

    @Cacheable(value = "user",key = "#id")
public User findById(Integer id){
if(id.equals(10)){
System.out.println("running......");
return new User(10,"jack");
}
System.out.println("running2......");
return new User(new Random().nextInt(),"tom");
}

    除了上面最简单的形式外@Cacheable与@CachePut还有一些可选的属性,如下,

    

属性 类型 描述
value String[] 要使用的缓存名称
condition String SpEL表达式,若值为false,不会讲缓存应用到方法上
key String SpEL表达式,用于计算自定义的缓存key
unless String SpEL表达式,若为true,返回值不会被缓存。

    @Cacheable还可以放到接口中的方法声明上,这样的话所有对该方法的实现都会应用相同的缓存规则。

  2、@CacheEvict

      该注解从缓存中移除内容,与@Cacheable和@CachePut不同,@CacheEvict可用于返回类型为void。示例如下:

1    @CacheEvict(value = "user",key = "#id")
2 public void remove(Integer id){
3 System.out.println("remove a user...");
4 }
      

    当调用此方法时,会从缓存中移除一个元素,被删除条目的key与传进来的key值相同(此处使用SpEL指定)。

    @CacheEvict的属性有以下几项:

    

属性  类型 描述
value String[] 要使用的缓存名称
key String SpEL表达式,用于计算自定义的缓存key
condition String SpEL表达式,若值为false,不会讲缓存应用到方法上
allEntries boolean 若为true,特定缓存的所有条目都会被移除掉
beforeInvocation boolean 若为true,在方法调用之前移除条目,false,在方法成功调用之后再移除条目

   3、@Caching    

      @Caching允许多个嵌套 @Cacheable@CachePut@CacheEvict注解相同的方法来使用,示例如下:

   @Caching(evict = { @CacheEvict("primary"),@CacheEvict(cacheNames="secondary", key="#user.id")})
public User modify(User user){
user.setUsername("admin");
return user;
}

    不同的缓存注解使用不同的缓存名称或者不同的条件表达式加以区分。

  4、@CacheConfig

    @CacheConfig是一个类级注释,允许共享缓存名称,自定义 KeyGenerator,自定义CacheManager和自定义CacheResolver。将此批注放在类上不会打开任何缓存操作。

    如下,设置了该类下所有方法缓存的名称为user:

    

@Service
@CacheConfig(cacheNames = "user")
public class UserService {
............
}

    方法级别指定的配置始终会覆盖类级的@CacheConfig。因此,这为每个缓存操作提供了三个级别的自定义:

    • 全局,可用于CacheManagerKeyGenerator

    • 类级,使用@CacheConfig

    • 方法级。

   5、自定义缓存key

    @Cacheable、@CachePut以及@CacheEvict都有一个名为key的属性,这个属性能够替换默认的key,他通过一个SpEL计算得来,一般都是所定义的表达式与存储在缓存中的值有关,根据此计算得到key。

    在为缓存编写的SpEL中,spring暴露了一些很有用的元数据。

表达式 描述
#root.args 传递给缓存方法的参数,形式为数组
#root.caches 该方法执行时所对应的缓存,形式为数组
#root.target 目标对象
#root.targetClass 目标对象的类
#root.method 缓存的方法
#root.methodName 缓存方法的名称
#result 方法调用的返回值(不能在@Cacheable上)
#Argument 任意的方法参数名(如argName)或参数索引(#a0,#p0)

    6、条件化缓存

      @Cacheable、@CachePut均提供了两个属性实现条件化缓存:unless、condition,这两个属性都接受一个SpEL表达式。若unless属性的SpEL属性计算为true缓存将不会放到缓存中,condition属性的SpEL计算若为false,那么该方法的缓存会被禁掉。

      两者的差别:

        unless只能阻止将对象放进缓存,在方法调用的时候依然回去缓存中查找,如找到,则返回找到的值。unless可以引用#result

        condition的表达式计算结果为false,那么在这个方法调用的过程中,缓存是被禁用的。condition不能引用#unless

    示例如下:

    

 @Cacheable(key = "#id",unless = "#result.id==10",condition = "#id>=23")
public User findOne(Integer id){
if(id.equals(10)){
System.out.println("findOne......");
return new User(10,"jack");
}
System.out.println("findOne......");
return new User(new Random().nextInt(),"tom");
}

  当传入的Id为10时,不会将结果放到缓存中,当Id大于23时会直接禁用缓存。

    

         

spring中使用缓存的更多相关文章

  1. 分布式数据存储 之 Redis(二) —— spring中的缓存抽象

    分布式数据存储 之 Redis(二) -- spring中的缓存抽象 一.spring boot 中的 StringRedisTemplate 1.StringRedisTemplate Demo 第 ...

  2. spring中的缓存--Caching

    1.spring从3.1开始支持缓存功能.spring 自带的缓存机制它只在方法上起作用,对于你使用其他持久化层的框架来讲,是没有影响的,相对来讲这种缓存方式还是不错的选择. 2.提供缓存的接口:or ...

  3. spring中配置缓存—ehcache

    常用的缓存工具有ehcache.memcache和redis,这里介绍spring中ehcache的配置. 1.在pom添加依赖: <!-- ehcache 相关依赖 --> <de ...

  4. redis—Spring中redis缓存的简单使用

    这里使用的是 Spring-4.3 , redis-2.8 的版本   1.添加maven依赖 <dependency> <groupId>redis.clients</ ...

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

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

  6. 浅析redis缓存 在spring中的配置 及其简单的使用

    一:如果你需要在你的本地项目中配置redis.那么你首先得需要在你的本地安装redis 参考链接[http://www.runoob.com/redis/redis-install.html] 下载r ...

  7. spring(三、spring中的eheche缓存、redis使用)

    spring(三.spring中的eheche缓存.redis使用) 本文主要介绍为什么要构建ehcache+redis两级缓存?以及在实战中如何实现?思考如何配置缓存策略更合适?这样的方案可能遗留什 ...

  8. 学习Spring Boot:(十九)Shiro 中使用缓存

    前言 在 shiro 中每次去拦截请求进行权限认证的时候,都会去数据库查询该用户的所有权限信息, 这个时候就是有一个问题了,因为用户的权限信息在短时间内是不可变的,每次查询出来的数据其实都是重复数据, ...

  9. 在Spring中使用Redis Lua脚本批量删除缓存

    背景 之前分享了一篇利用lua脚本批量删除redis的key的文章.现在项目中我打算使用spring的缓存,而Spring缓存以前我是用ehcache来做实现的.没发现什么问题..这次我换成redis ...

随机推荐

  1. python-xlrd 实现excel 导入数据

    首先安装 xlrd 两种方式: 1.wheel 方式 安装: 首先要下载 wheel :

  2. Python类(八)-类的起源

    首先用type()看一下类和实例化对象的类型 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" class Person(obj ...

  3. java 字符串和集合互相转换

    今天在写项目的时候遇到一个问题,就是要把得到的一个集合转换成字符串,发现 import org.apache.commons.lang.StringUtils; 有这么一个简单的方法:String s ...

  4. 什么是SPU、SKU、SKC、ARPU

    首先,搞清楚商品与单品的区别.例如,iphone是一个单品,但是在淘宝上当很多商家同时出售这个产品的时候,iphone就是一个商品了. 商品:淘宝叫item,京东叫product,商品特指与商家有关的 ...

  5. 问题:C#Chart控件自动添加Series;结果:图形组件Chart动态添加Series

    Chart1.DataSource = dtb; string[] strcolor = new string[20]; strcolor[0] = "220, 224, 64, 10&qu ...

  6. java线程游戏之背景图片的移动

    package com.plane; import java.awt.Graphics; import java.awt.Image; import javax.swing.ImageIcon; im ...

  7. Android按钮单击事件的四种常用写法

    这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的写法都有 ...

  8. Codeforces #536 div2 E (1106E)Lunar New Year and Red Envelopes (DP)

    题意:过年了,Bob要抢红包.抢红包的时间段为1 - n,有m个红包,每个红包有三个属性:st(红包出现的时间), ed(红包消失的时间),d(如果抢了这个红包,能够抢下一个红包的时间),w(红包的收 ...

  9. OpenGL超级宝典完整源码(第五版)

    链接:https://pan.baidu.com/s/1dGQkk4T 密码:wu44 Visual Studio 2017配置OpenGL https://blog.csdn.net/qiangbi ...

  10. vue 之 表单输入绑定

    vue的核心:声明式的指令和数据的双向绑定. 那么声明式的指令,已经给大家介绍完了.接下来我们来研究一下什么是数据的双向绑定? 另外,大家一定要知道vue的设计模式:MVVM M是Model的简写,V ...