Spring Cache整合Ehcache或Redis or others
使用Spring Cache需要我们做两方面的事:
n 声明某些方法使用缓存
n 配置Spring对Cache的支持
和Spring对事务管理的支持一样(AOP实现的),Spring对Cache的支持也有基于注解和基于XML配置两种方式。
1 基于注解的支持
Spring为我们提供了几个注解来支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable标记的方法在执行后Spring Cache将缓存其返回结果,而使用@CacheEvict标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。下面我们将来详细介绍一下Spring基于注解对Cache的支持所提供的几个注解。
Spring Cache整合Ehcache : http://haohaoxuexi.iteye.com/blog/2123030
<?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/>
<!-- Ehcache实现 -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"p:cache-manager-ref="ehcacheManager"/>
<bean id="ehcacheManager"class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache-spring.xml"/>
</beans>
使用:
@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;
}
@CacheEvict(value="users", allEntries=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
问题:
- <cache:annotation-driven cache-manager="cacheManager" mode="aspectj" proxy-target-class="true"/>
为什么设置了mode="aspectj" 和 proxy-target-class="true" 在内部调用的时候还是会查询数据库
这属于AOP的问题,AOP在内部调用时是不会进行代理的,Spring的缓存技术也是基于AOP实现的,所以你用的内部调用会查询数据库,而不是从缓存中获取。
Spring Cache整合Redis
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import java.lang.reflect.Method;
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator zKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method,
Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(
@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
// Number of seconds before expiration. Defaults to unlimited (0)
cacheManager.setDefaultExpiration(300);
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(
RedisConnectionFactory factory) {
final StringRedisTemplate template = new StringRedisTemplate(factory);
template.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(
Object.class)); // 请注意这里
return template;
}
}
@Cacheable(value="users", key="zKeyGenerator")
public User find(User user) {
System.out.println("find user by user " + user);
return user;
}