一、启用对缓存的支持

  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. 第十三章 Spring框架的设计理念与设计模式分析(待续)

    Spring的骨骼架构 核心组件详解 Spring中AOP的特性详解 设计模式解析之代理模式 设计模式解析之策略模式

  2. CentOS 7.2 部署Rsync + Lsyncd服务实现文件实时同步/备份 (一)

    接收端配置: 1.安装rsync yum -y install rsync 2.配置同步模块 1. 编辑同步配置文件 vi /etc/rsyncd.conf 2. 同步模块配置参数 # any nam ...

  3. jackson 进行json与java对象转换 之一

    代码无真相,为了最简单的说明,我直接上代码. public class User { private String name; private Gender gender; private List& ...

  4. 问题:oracle 排序 null值放在最后;结果: ORACLE中null的排序问题

    ORACLE中null的排序问题 关键字: oracle nulls 问题描述:    在平时的业务处理中,经常遇到要对业务数据进行排序,并且要对null值也做相应的排序.在Oracle中,进行Ord ...

  5. numpy.percentile

    http://docs.scipy.org/doc/numpy/reference/generated/numpy.percentile.html numpy.percentile(a, q, axi ...

  6. 基于Flask框架的Python web程序的开发实战 <二> 项目组织结构

    看到第七章-大型程序的结构,备受打击,搞不清工厂函数.蓝本.单元测试,不理解这些对象/变量怎么传递的,感觉好乱,虽然按照源码都照抄了,还是不理解.... 缓缓先.... 本来网上的Flask的教程就比 ...

  7. python之数据库的操作(课前准备)

    数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. 上面的就是数据库的定义. 何为数据库,简单的来说,就是我们的大型数据的存放地点. 而我们学习的呢就是数据库的访问层的制作. 何为 ...

  8. C语言基础问题总结

    Double 类型用 %f 接受会产生错误,应该用%lf C语言中SIN,COS的参数为弧度,角度应先转换为弧度才能计算,否则出错 三角形的判断条件,任意两边长度和大于第三边 闰年判断条件整百年为40 ...

  9. java中public static void main(String[] args)中String[] args代表什么意思?

    这是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法.跟C语言里面的main()函数的作用是一样的.只有有main()方法的java程序才能够被java虚拟机欲行,可理解为 ...

  10. c++ 拷贝构造函数 继承

    拷贝构造函数要求把所有变量都需要做拷贝.在有继承关系情况先,子类的拷贝构造函数,需要调用父类拷贝构造函数.示例代码如下: class Base{ public: virtual ~Base(); Ba ...