Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。
Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache 集成。
package com.learn.frame.spring.cache;
import org.springframework.cache.annotation.Cacheable;
public class Book {
/**
* value : 缓存的名字 ,key : 缓存map中的key
* @param id
* @return
*/
@Cacheable(value = { "sampleCache" },key="#id")
public String getBook(int id) {
System.out.println("Method executed..");
if (id == 1) {
return "Book 1";
} else {
return "Book 2";
}
}
}
@Cacheable(value=“sampleCache”),这个注释的意思是,当调用这个方法的时候,会从一个名叫 sampleCache 的缓存(缓存本质是一个map)中查询key为id的值,如果不存在,则执行实际的方法(即查询数据库等服务逻辑),并将执行的结果存入缓存中,否则返回缓存中的对象。这里的缓存中的 key 就是参数 id,value 就是 返回的String 对象
1.value : 指定一个或多个Cache名字,同属性cacheNames
@Cacheable(value ="sampleCache")
@Cacheable(cacheNames="sampleCache")
2.key : 存储对象的key
a)使用自定义策略 (#参数名 或 #参数.属性名 ) 的方式动态定义key
除了使用方法参数作为key,我还可以使用root对象来生成key
属性名称 |
描述 |
示例 |
methodName |
当前方法名 |
#root.methodName |
method |
当前方法 |
#root.method.name |
target |
当前被调用的对象 |
#root.target |
targetClass |
当前被调用的对象的class |
#root.targetClass |
args |
当前方法参数组成的数组 |
#root.args[0] |
caches |
当前被调用的方法使用的Cache |
#root.caches[0].name |
1.spring 默认使用root对象属性,#root可以省略
@Cacheable(value = { "sampleCache" ,"sampleCache2"},key="cache[1].name")
public String getBook(int id) {
System.out.println("Method executed..");
if (id == 1) {
return "Book 1";
} else {
return "Book 2";
}
}
2.自定义 key = 类名.方法名.参数值 添加字符用单引号
@Cacheable(value = { "sampleCache","sampleCache2" },key="targetClass.getName()+'.'+methodName+'.'+#id")
public String getBook(int id) {
System.out.println("Method executed..");
if (id == 1) {
return "Book 1";
} else {
return "Book 2";
}
}
b)除了使用key指定外,Spring还提供了org.springframework.cache.interceptor.KeyGenerator
接口,使用keyGenerator去指定实现此接口的bean的名字
@Cacheable(cacheNames="sampleCache", keyGenerator="myKeyGenerator")
3.注意@Cacheable配置多个cache时需要在CacheManager中同样注册对应cache,否则包错 Cannot find cache named 'sampleCacheXXX'
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("sampleCache"),new ConcurrentMapCache("sampleCache2")));
return cacheManager;
}
3.cacheManager 指定缓存管理器
应用程序使用多个缓存管理器,去设置cacheManager给
每个操作使用
@Cacheable(cacheNames="books", cacheManager="anotherCacheManager")
4.condition : 指定发生条件
@Cacheable(condition="#id >5") 参数id 大于5时加入缓存
package com.learn.frame.spring.cache;
import java.util.Arrays;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* spring cache 缓存的使用
* @author Administrator
*
*/
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public Book book() {
return new Book();
}
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("sampleCache")));//注册名为sampleCache的缓存
return cacheManager;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(CachingConfig.class);
ctx.refresh();
Book book = ctx.getBean(Book.class);
// calling getBook method first time.
System.out.println(book.getBook(1));
// calling getBook method second time. This time, method will not
// execute.
System.out.println(book.getBook(1));
// calling getBook method third time with different value.
System.out.println(book.getBook(2));
ctx.close();
}
}
@EnableCaching注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了,等价于
CacheManager : 管理Cache对象
Cache : 用合适的数据结构存储数据(上述例子使用ConcurrentMapCache map结构存储数据对象)
上面的java config和下面的xml配置文件是等效的
定义了一个缓存管理器SimpleCacheManager 并设置名称为sampleCache的缓存,@Cachable的value属性要和此对应。
测试输出结果
Method executed..
Book 1
Book 1
Method executed..
Book 2
拓展:我们可以使用redis来代替Map,将数据缓存到第三方容器(如redis)中 redisson整合Spring 缓存
参考 Spring Cache