Java Caching定义了五个接口,分别是CachingProvider、CacheManager、Cache、Entry、Expiry。
注:应用程序先访问缓存提供者CachingProvider,CachingProvider管理了多个缓存管理器CachingManager,而CachingManage里面才管理了多个真正的缓存Cache组件,跟系统进行缓存的CRUD操作用到的是Cache组件。
JSR107中定义了很多简化缓存开发的注解,但并不是所有的缓存组件都提供了JSR107的实现,需要自己编写JSR107的实现,难度也较大,所以JSR107用的比较少。为了简化开发,Spring提供了自己的缓存抽象,也定义了类似JSR107的注解。
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;
Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;
注解 | 备注 |
---|---|
@Cacheable | 先查找缓存 , 有就返回 ,没有就执行方法 ,并将结果缓存起来 |
@Cacheput | 先执行方法 , 再将结果缓存起来 |
@CacheEvict | 删除缓存数据 |
@EnableCaching | 开启基于注解的缓存 |
@CacheConfig | 作用在类上,抽取缓存的公共配置 |
参数 | 备注 | 举例 |
---|---|---|
keyGenerator | 缓存数据时key生成策略 | |
serialize | 缓存数据时value序列化策略 | |
value | 缓存的名称,至少一个 | @Cacheable(value=”mycache”) |
key | 缓存的key,默认是方法的参数 | @Cacheable(value=”testcache”,key=”#userName”) |
condition | 指定符合条件的情况下才缓存 | @Cacheable(condition=”#userName.length()>2”) |
unless | 当unless指定的条件为true,方法的返回值就不会被缓存 | @Cacheable(unless=”#result == null”) |
allEntries | 是否清空所有缓存,默认false | @CachEvict(allEntries=true) |
beforeInvocation | 是否在执行方法区就清空缓存,默认false | @CachEvict(beforeInvocation=true) |
sync | 是否使用异步模式,默认false,使用了sync就不能使用unless |
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
@SpringBootApplication
@EnableCaching //开启注解缓存
public class SpringCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheApplication.class, args);
}
}
package com.cao.service;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* @author:秋一叶
* @date:2020-12-02 9:23
*/
//抽取缓存的公共配置-缓存key
@CacheConfig(cacheNames = CacheService.CACHE_KEY)
@Service
public class CacheService {
//缓存key
public static final String CACHE_KEY = "test-cache";
/**
* 获取缓存:没有缓存就执行方法并将结果缓存起来;
*/
@Cacheable(cacheNames = CACHE_KEY)
public String getCache(String id){
return getString(id);
}
/**
* 更新缓存:先执行方法,再将结果缓存起来;
*/
@CachePut(cacheNames = CACHE_KEY)
public String updateCache(String id){
return getString(id);
}
/**
* 清除缓存:删除缓存数据
*/
@CacheEvict(cacheNames = CACHE_KEY)
public void removeCache(String id){
System.out.println("删除缓存" + id);
}
/**
* 获取String,模拟调用方法
* @param id
* @return
*/
public String getString(String id){
return id;
}
}
引入了缓存相关的依赖,缓存的自动配置类CacheAutoConfiguration就会生效,CacheAutoConfiguration自动导入了CacheConfigurationImportSelector;
1、缓存的自动配置类;CacheAutoConfiguration
2、缓存的配置类
3、哪个配置类生效
application.properties:
#开启自动配置报告
debug=true
org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认使用这个】
默认是SimpleCacheConfiguration,给容器中注册了一个缓存管理器ConcurrentMapCacheManager,可以获取和创建ConcurrentMapCache类型的缓存组件,ConcurrentMapCache的作用可以将数据保存在ConcurrentMap中。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
引入了redis相关的场景,RedisCacheConfiguration自动配置类就起作用了;
#开启自动配置报告
#debug=true
#配置redis
spring.redis.host=192.168.6.21
package com.cao;
import com.cao.spring_guava.springboot_cache.User;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootCacheApplicationTests {
@Autowired
private RedisTemplate redisTemplate; //操作k-v都是字符串的
@Autowired
private StringRedisTemplate stringRedisTemplate; //操作k-v都是对象的
@Test
public void redisCacheTest() {
User user = new User();
user.setName("秋一叶");
user.setAge(18);
redisTemplate.opsForValue().set("用户", user);
}
}
package com.cao.spring_guava.springboot_cache.config;
import com.cao.spring_guava.springboot_cache.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
/**
* @Author 秋一叶
* @Date 2020/12/16 - 21:35
*/
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, User> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> userJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(userJackson2JsonRedisSerializer);
return template;
}
}
package com.cao;
import com.cao.spring_guava.springboot_cache.User;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootCacheApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate<Object, User> userRedisTemplate; //使用自定义的redisTemplate
@Test
public void redisCacheTest() {
User user = new User();
user.setName("秋一叶");
user.setAge(18);
userRedisTemplate.opsForValue().set("用户", user);
}
}
package com.cao.spring_guava.springboot_cache.config;
import com.cao.spring_guava.springboot_cache.User;
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.serializer.Jackson2JsonRedisSerializer;
/**
* @Author 秋一叶
* @Date 2020/12/16 - 21:35
*/
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, User> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> userJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(userJackson2JsonRedisSerializer);
return template;
}
//自定义缓存管理器
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, User> userRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(userRedisTemplate);
return cacheManager;
}
}