spring中使用缓存
一、启用对缓存的支持
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。因此,这为每个缓存操作提供了三个级别的自定义:
全局,可用于
CacheManager,KeyGenerator。类级,使用
@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中使用缓存的更多相关文章
- 分布式数据存储 之 Redis(二) —— spring中的缓存抽象
分布式数据存储 之 Redis(二) -- spring中的缓存抽象 一.spring boot 中的 StringRedisTemplate 1.StringRedisTemplate Demo 第 ...
- spring中的缓存--Caching
1.spring从3.1开始支持缓存功能.spring 自带的缓存机制它只在方法上起作用,对于你使用其他持久化层的框架来讲,是没有影响的,相对来讲这种缓存方式还是不错的选择. 2.提供缓存的接口:or ...
- spring中配置缓存—ehcache
常用的缓存工具有ehcache.memcache和redis,这里介绍spring中ehcache的配置. 1.在pom添加依赖: <!-- ehcache 相关依赖 --> <de ...
- redis—Spring中redis缓存的简单使用
这里使用的是 Spring-4.3 , redis-2.8 的版本 1.添加maven依赖 <dependency> <groupId>redis.clients</ ...
- 在Spring中使用cache(EhCache的对象缓存和页面缓存)
Spring框架从version3.1开始支持cache,并在version4.1版本中对cache功能进行了增强. spring cache 的关键原理就是 spring AOP,通过 spring ...
- 浅析redis缓存 在spring中的配置 及其简单的使用
一:如果你需要在你的本地项目中配置redis.那么你首先得需要在你的本地安装redis 参考链接[http://www.runoob.com/redis/redis-install.html] 下载r ...
- spring(三、spring中的eheche缓存、redis使用)
spring(三.spring中的eheche缓存.redis使用) 本文主要介绍为什么要构建ehcache+redis两级缓存?以及在实战中如何实现?思考如何配置缓存策略更合适?这样的方案可能遗留什 ...
- 学习Spring Boot:(十九)Shiro 中使用缓存
前言 在 shiro 中每次去拦截请求进行权限认证的时候,都会去数据库查询该用户的所有权限信息, 这个时候就是有一个问题了,因为用户的权限信息在短时间内是不可变的,每次查询出来的数据其实都是重复数据, ...
- 在Spring中使用Redis Lua脚本批量删除缓存
背景 之前分享了一篇利用lua脚本批量删除redis的key的文章.现在项目中我打算使用spring的缓存,而Spring缓存以前我是用ehcache来做实现的.没发现什么问题..这次我换成redis ...
随机推荐
- PDM生成数据库-0设置表名和字段名中不带双引号
如果PDM直接导出脚本的话,所有的表和字段都会被加上双引号,非常不方便,去除双引号的办法: Database->Edit Current DBMS在弹出窗体中第一项General中找到 Scri ...
- Compare and Swap(CAS)
CAS(Compare and Swap)是个原子操作.拿到一个新值后,CAS将其与内存中的值进行比较,若内存中的值和这个值不一样,则将这个值写入内存,否则,不做操作.在Java的 java.util ...
- DAY9-python并发之多进程
一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...
- Eclipse Maven 编译错误 Dynamic Web Module 3.0 requires Java 1.6 or newer 解决方案
Eclipse Maven 开发一个 jee 项目时,编译时遇到以下错误:Description Resource Path Location TypeDynamic Web Module 3.0 r ...
- 前端页面给指定的div添加遮罩层,并且带有加载中的小旋转图片
话不多说,先上代码,其实还是比较简单的 $("<div id='shade' style='opacity:0.85;background:white'></div> ...
- Contset Hunter 1102 高精度求卡特兰数
用递推的方式写的写挂了,而如果用组合数又不会高精度除法,偶然看到了别人的只用高精度乘低精度求组合数的方法,记录一下 #include<bits/stdc++.h> using namesp ...
- ROS与Matlab系列:一个简单的运动控制
ROS与Matlab系列:一个简单的运动控制 转自:http://blog.exbot.net/archives/2594 Matlab拥有强大的数据处理.可视化绘图能力以及众多成熟的算法函数,非常适 ...
- 前端学习笔记2017.6.12 CSS控制DIV
前一篇文章中用div布局了豆瓣东西的页面,如果用html代码表示的话大概是这个样子的 <!DOCTYPE html><html><head></head> ...
- HiveServer2的配置使用
HiveServer2的配置和使用 hive-site.xml配置 hiveserver2的配置 <property> <name>hive.support.concurren ...
- java快排(两种方法)
快排是最基础的排序算法之一,今天来回顾一下. public class QuickSort { public static void quickSort(int[] array){ if(array ...