Spring对缓存的支持类似于对事务的支持,Spring缓存的思想是在调用方法时,会把该方法的参数和返回结果作为一个键值对存放于缓存中,下次在调用该方法时直接从缓存返回结果。
Spring支持两种设置方法,注解和xml
1.配置缓存的注解驱动
可以直接创建配置缓存的xml配置文件,或者直接再原spring配置文件中添加,缓存的注解驱动
<cache:annotation-driven/>
创建配值文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager"/>
</beans>
或者如果spring的配置文件为java,可以直接再类上添加@EnableCaching注解
@Configuration
@EnableCaching
public class CachingConfig{
@Bean
public CacheManager cacheManager(){
return new ConcurrentMapCacheManager();
}
}
<cache:annotation-driven/> 和 @EnableCaching 都是创建了一个切面并触发spring缓存注解的切点,这个切面负责管理缓存
同时除了上面配置的ConcurrentMapCacheManager缓存管理器,spring还提供了许多其他的缓存管理器,如:EhCacheCacheManager,SimpleCacheManager,RedisCacheManager等
使用Redis缓存
RedisCacheManager与Redis服务器协作,通过RedisTemplate将缓存存储到Redis中。
@Configuration
@EnableCaching
public class CachingConfig{
//缓存管理器bean
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate){
return new RedisCacheManager(redisTemplate);
}
//连接工厂bean
@Bean
public JedisConnectionFactory redisConnectionFactory(){
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.afterPropertiesSet()
return jedisConnectionFactory;
}
@Bean
//redisTemplate 的bean类
public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory redisCF){
RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory()
redisTemplate.afterPropertiesSet()
return redisTemplate;
}
}
当然多个缓存管理器之间可以混合使用,返回一个缓存管理的列表即可。
@Configuration
@EnableCaching
public class CachingConfig{
@Bean
public CacheManager cacheManager(net.sf.ehcache.CacheManager cm,javax.cache.CacheManager jcm){
CompositeCacheManager cacheManager = new CompositeCacheManager();
List<CacheManager> managers = new ArrayList<>();
managers.add(new JCacheCacheManager(jcm));
managers.add(new EhcacheCacheManager(cm));
managers.add(new RedisTemplate(redisTemplate));
return cacheManager;
}
}
2.为方法添加注解支持缓存
如果注解在方法上,缓存行为只会在方法上,如果注解在类上,缓存行为就会应用到这个类的所有方法上。
- @Cacheable 在spring调用方法之前,首先应该在缓存中查找方法的返回值,如果无,方法被调用。
@Cacheable可以指定三个属性,value、key和condition。
value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。
@Cacheable("cache1")//Cache是发生在cache1上的
public User find(Integer id) {
return service.getUserById(id);
}
@Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
public User find(Integer id) {
return service.getUserById(id);
}
key属性是用来指定Spring缓存方法的返回结果时对应的key的。
@Cacheable(value="users", key="#id")
public User find(Integer id) {
return service.getUserById(id);
}
可以使用spel语言自动生成key,例如
root.methodName
root.target
id
condition可以指定发生的条件,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
System.out.println("find user by user " + user);
return user;
}
- @CachePut
spring会将方法的返回值放到缓存中,调用前不会检测缓存。
@CachePut 也可以指定三个属性,value、key和condition。
- @CacheEvict
spring应该在缓存中清除一个或多个条目。
@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation
allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。
@CacheEvict(value="users", allEntries=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
清除操作默认是在对应方法成功执行之后触发的,使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@CacheEvict(value="users", beforeInvocation=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
- @Caching
@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。
@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
@CacheEvict(value = "cache3", allEntries = true) })
public User find(Integer id) {
return service.getUserById(id);
}
网友评论