数据库的读写并发一直都是应用性能的瓶颈所在之一,针对改动频率很小的数据我们应该将他存放到缓存中,减少与数据库的交互。
启用对缓存的支持
Spring 对缓存的支持有两种方式:
- 注解驱动的缓存
- XML 申明的缓存
为了避免繁琐的 XML 配置文件,我们这边只讲解注解驱动的形式。
启用缓存功能
@Configuration
// 启用缓存功能
@EnableCaching
public class CachingConfig {
/**
* 申明缓存管理器
* @return
*/
@Bean
public CacheManager cacheManager(){
return new ConcurrentMapCacheManager();
}
}
缓存管理器
Spirng 3.1 内置了五个缓存管理器实现:
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
Spring 3.2 又提供了两个缓存管理器:
- RedisCacheManager
- GemfireCacheManager
使用 Redis 缓存
配置 Redis 缓存管理器
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
RedisCacheManager redisTemplate = RedisCacheManager.create(redisConnectionFactory);
return redisTemplate;
}
}
为方法增加注解以支持缓存
Spring 缓存很大程度上是围绕切面构建的,在 Spring 中启用缓存时,它会创建一个切面用来实现缓存功能。Spring 提供了下面几个注解:
注解 | 作用 |
---|---|
@Cacheable | 表明 Spring 在方法调用之前,先在缓存中查找方法的返回值,如果没有找到才会调用方法,并且将方法的返回值放入缓存中 |
@CachePut | 表明 Spring 应该将方法的返回值放到缓存中。在方法的调用前并不会检查缓存,方法始终会被调用 |
@CacheEvict | 表明 Spring 应用在缓存中清除一个或多个条目 |
@Caching | 这是一个分组的注解,能够同时应用多个其他的缓存注解 |
@Cacheable 和 @CachePut 注解都是将值放入到缓存中去,它们有一些共有的属性:
属性 | 类型 | 描述 |
---|---|---|
values | String[] | 要使用的缓存名称 |
condition | String | SqEL 表达式,如果值为 false,不会将缓存应用到方法调用上 |
key | String | SqEL 表达式,用来计算自定义的缓存 key |
unless | String | SqEL 表达式,如果得到的值是 true,返回值不会放到缓存中去 |
最简单的情况下,只需要指定 value 属性即可。
实例
dao 对象:
@Repository
public class UserDao {
@Cacheable(value = "accountUser")
public User findUserByAccount(String account) {
System.out.println("方法被调用");
User user = new User();
user.setAccount(account);
return user;
}
}
单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootConfig.class)
public class CachingTest {
@Autowired
private UserDao userDao;
@Test
public void testFindUserByAccount(){
System.out.println("==========第一次==========");
User user1 = userDao.findUserByAccount("admin");
Assert.assertNotNull(user1);
System.out.println("==========第二次==========");
User user2 = userDao.findUserByAccount("admin");
Assert.assertNotNull(user2);
}
}
控制台输出:
==========第一次==========
方法被调用
==========第二次==========
实例中使用的是 @Cacheable 注解,可以看到第一次调用的时候,缓存中还没有数据,所以方法被调用;第二次调用的时候发现缓存中有数据,所以不再调用方法