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 ...
随机推荐
- web页面导出到Excel乱码解决
引言: 前几天 在做web项目的时候 需要导出页面上的数据 到Excel里面 但有的时候出现乱码(有de时候不出现 很奇怪) 原来的代码是这样的: HttpContext.Current.Respon ...
- 深入理解CPU和异构计算芯片GPU/FPGA/ASIC (下篇)
3.2.1 CPU计算能力分析 这里CPU计算能力用Intel的Haswell架构进行分析,Haswell架构上计算单元有2个FMA(fused multiply-add),每个FMA可以对256bi ...
- List里将某字段相同的元素合并
工作中遇到将List中某字段相同的元素合并,笔者觉得有必要记录下来,以备以后参考,好了,直接上代码 import java.util.ArrayList; import java.util.List; ...
- python爬虫实战(1)--爬取糗事百科
这里利用正则表达式进行匹配,糗事百科是不需要登录的,所以也没必要用到Cookie,另外糗事百科有的段子是附图的,我们把图抓下来图片不便于显示,那么我们就尝试过滤掉有图的段子. 本篇目标 1.抓取糗事百 ...
- MyBatis总结七:动态sql和sql片段
开发中,sql拼接很常见,所以说一下动态sql: 1 if 2 chose,when,otherwise 3 where,set 4 foreach 用法解析(现有一张users表 内有id user ...
- Android常用开源库集合【持续更新】
1.FastJson 阿里巴巴工程师做的一个方便的JSON转换库 2.ButterKnife 只要作用能代替代码中大量的findviewbyid语句的使用,使用@injectview注入方式 3.v ...
- mybatis项目报错:java.sql.SQLException: ORA-00911: 无效字符 解决方法
如果你用java写程序访问数据库,出现这个问题:java.sql.SQLException: ORA-00911: 无效字符 at oracle.jdbc.driver.DatabaseError.t ...
- LINUX关闭防火墙、开放特定端口等常用操作
1. 重启后永久性生效: 开启:chkconfig iptables on 关闭:chkconfig iptables off 2. 即时生效,重启后失效: 开启:service iptables s ...
- Blender 软件 四视图布局的创建方法
Blender 软件 四视图布局的创建方法 我使用的Blender版本:Blender V 2.77 Q: 为什么要创建一个:四视图布局场景? A: 原因1:四视图布局最适合模型建模.原因2:在 Bl ...
- 《Effective Java》第8章 通用程序设计
第47条:了解和使用类库 Top 100 Java Libraries on Github 2016 Library Number of Projects Type % of projects jun ...