Springboot缓存的使用
- 什么是缓存
- spring缓存是什么
- spring中缓存的注解
- @EnableCaching
- @Cacheable
- @CachePut
- @CacheEvict
- @CacheConfig
- 总结
什么是缓存
缓存是为了解决CPU速度和内存速度的速度差异问题。内存中被CPU访问最频繁的数据和指令被复制入CPU中的缓存,这样CPU就可以不经常到象“蜗牛”一样慢的内存中去取数据了,CPU只要到缓存中去取就行了,而缓存的速度要比内存快很多。
spring缓存是什么
反正也就一个道理,存储一些我们经常要用的的数据
减轻数据库的压力
spring中缓存的注解
@EnableCaching
- 是什么
开启基于注解的缓存 - 怎么用
标注在方法类中
@EnableCaching//开启缓存注解
public class BookService {
}
@Cacheable
- 是什么
当第一次访问的时候,把结果返回给用户,并把结果数据存到缓存中,下次访问不经过方法,直接返回缓存中的数据,一般用作查找 - 参数有什么
key | 作用 |
cacheNames/value | 表示缓存组件的名字 |
key/keyGenerator | 表示存储到缓存的键名,可以用spel表达式/key的生成策略 |
cacheManager/cacheResolver | 指定用什么做管理器,管理多个组件,比如用redis的缓存,或者自带的默认的concurrenthashmap |
condition | 条件成功缓存,可以用spel表达式 |
unless | 条件成功不缓存,可以用spel表达式 |
3,举例子
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
Long bookId;
String bookName;
}
service层(用静态代码块不连接数据库了 方便一点。。。)
@Component
@EnableCaching//开启缓存注解
public class BookService {
public static HashMap<Long, Book> map = new HashMap<>();
static {
map.put(1L,new Book(1L,"老人与海"));
map.put(2L,new Book(2L,"海的女儿"));
map.put(3L,new Book(3L,"红高粱"));
}
@Cacheable(value = "book",key = "#id")
public Book getBookById(Long id){
Book book = map.get(id);
System.out.println(book);
return map.get(id);
}
}
控制层
@RestController
public class BookController {
@Autowired
BookService bookService;
@GetMapping("/get")
public Book getByBookId(Long id){
return bookService.getBookById(id);
}
}
开机启动
第一次访问
清空控制台第二次访问
没有任何打印,说明缓存成功了?
那么它存储到哪里去了
经过调试
在CacheConfigurations中有这么一段代码存放着缓存配置
static {
Map<CacheType, Class<?>> mappings = new EnumMap(CacheType.class);
mappings.put(CacheType.GENERIC, GenericCacheConfiguration.class);
mappings.put(CacheType.EHCACHE, EhCacheCacheConfiguration.class);
mappings.put(CacheType.HAZELCAST, HazelcastCacheConfiguration.class);
mappings.put(CacheType.INFINISPAN, InfinispanCacheConfiguration.class);
mappings.put(CacheType.JCACHE, JCacheCacheConfiguration.class);
mappings.put(CacheType.COUCHBASE, CouchbaseCacheConfiguration.class);
mappings.put(CacheType.REDIS, RedisCacheConfiguration.class);
mappings.put(CacheType.CAFFEINE, CaffeineCacheConfiguration.class);
mappings.put(CacheType.SIMPLE, SimpleCacheConfiguration.class);
mappings.put(CacheType.NONE, NoOpCacheConfiguration.class);
MAPPINGS = Collections.unmodifiableMap(mappings);
}
默认实现的就是
SimpleCacheConfiguration.class的配置
而这个配置类中有这么一段bean
@Bean
ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager);
}
在点进去一看发现存储的就是用concurrenthasp
难怪我之前实习的时候项目经理说你用缓存干嘛不自己写一个hashmap!!!
@CachePut
- 是什么
当第一次访问的时候,把结果返回给用户,并把结果数据存到缓存中,下次还访问方法,并重新设置缓存中的数据简单来说就是每次执行方法每次存数据!一般用作更新 - 注解参数
同@CachePut一样 - 测试
service
@CachePut(value = "book",key = "#a0.bookId")//#a0代表参数中第一个参数的bookId作为key
public Book updateBook(Book book){
System.out.println("要修改的书本数据:"+book);
map.put(book.getBookId(),book);
return map.get(book.getBookId());
}
控制层
@GetMapping("/update")
public Book updateBook(Book book){
Book book1 = bookService.updateBook(book);
return book1;
}
开机启动
查询数据
更新数据
在查询一次数据
数据改了,而且没在访问查询的代码而是直接访问缓存了(注意,缓存的key一定要一样根据id来)
@CacheEvict
- 是什么
根据key删除缓存一般用作删除 - 注解参数
同@CachePut一样
但是多了2个
key | 作用 |
allEntries | 是否需要清除管理器缓存中的所有元素默认为false |
beforeInvocation | 是否在方法前删除缓存默认false |
- 测试
service
@CacheEvict(value = "book",key = "#id")
public void delete(Long id){
System.out.println("删除缓存:"+id);
}
控制层
@GetMapping("/delete")
public String deleteBook(Long id){
bookService.delete(id);
return "删除成功";
}
启动
先查询id=1
这时候缓存了key=1的缓存,这时候我们删除缓存
我们在查询一下id=1
这时候发现缓存没了,执行方法里面
结束!
4. 测试(beforeInvocation)
service
@CacheEvict(value = "book",key = "#id",beforeInvocation = true)
public void delete(Long id){
System.out.println("删除缓存:"+id);
int a = 10/0;
map.remove(id);
}
控制层
@GetMapping("/delete")
public String deleteBook(Long id){
bookService.delete(id);
return "删除成功";
}
启动
先查询id=1
删除
我故意写个异常在里面,看看方法执行前有没有删除缓存
在执行查询
有执行方法体的内容了,说明在执行删除前已经删除缓存了!
在缓存后删除可以自行测试
还有那个allEntries 也可以自行测试
@CacheConfig
- 是什么
标注在类上,表面这个类所有方法的缓存的一些属性是都是这个 - 参数
key | 作用 |
cacheNames | 表示缓存组件的名字 |
keyGenerator | 表面key的生成策略 |
cacheManager/cacheResolver |
总结
这可能只是基本的使用
后续当我们用redis等中间件做缓存
根据spring规则注入使用
切忌!缓存最好不要乱用!!