package com.hosystem.cache.service;
?
import com.hosystem.cache.bean.Employee;
import com.hosystem.cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
?
@Service
@CacheConfig(cacheNames = "emp")
public class EmployeeService {
?
????@Autowired
????EmployeeMapper employeeMapper;
?
????/**
?????* ?将方法的运行结果进行缓存;下次在调用相同的数据,直接从缓存中获取,不再调用方法;
?????*
?????* ?CacheManager管理多个cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字
?????* ?工作原理:
?????* ?????1.自动配置类:CacheAutoConfiguration
?????* ?????2.缓存配置类:GenericCacheConfiguration、JCacheCacheConfiguration、EhCacheCacheConfiguration、HazelcastCacheConfiguration、InfinispanCacheConfiguration、CouchbaseCacheConfiguration、RedisCacheConfiguration、CaffeineCacheConfiguration、SimpleCacheConfiguration、NoOpCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
?????* ?????????org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
?????* ?????3.配置类默认生效:SimpleCacheConfiguration
?????* ?????4.给容器中注册了一个cacheManager:ConcurrentMapCacheManager
?????* ?????5.可以获取、创建ConcurrentMapCache类型的缓存组件;它的作用是将数据保存在ConcurrentMap中
?????*
?????* ?@Cacheable 运行流程:
?????* ?????1.方法运行之前,先去查找Cache(缓存组件),按照cacheNames指定的名字获取;(CacheManager先获取相应的缓存)第一次获取缓存如果没有该缓存则会自动创建
?????* ?????2.去Cache中查找缓存的内容,使用一个key,默认为方法的参数;
?????* ???????(1).key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key
?????* ???????(2).默认使用SimpleKeyGenerator生成key默认策略:若无参数,key = new SimpleKey();|如果有单个参数,key=参数值;|如果有多个参数,key = new SimpleKey(params);
?????* ?????3.若为查找到缓存就调用方法
?????* ?????4.将方法返回的结果,放入缓存中
?????* ?????@Cacheable 标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key查找缓存,如果缓存不存在,则运行方法并将结果放入缓存
?????* ?核心:
?????* ?????1.使用CacheManager[ConcurrentMapCacheManager]按照名字获取cache[ConcurrentHashMapCache]组件
?????* ?????2.key使用keyGenerator生成,默认是SimpleKeyGenerator
?????*
?????* ?属性:value、cacheNames、key、keyGenerator、cacheManager、cacheResolver、condition、unless、sync
?????* ?????value/cacheNames:指定缓存组件的名字
?????* ?????key:缓存数据使用的key,可以用它指定参数。默认是使用方法参数的值
?????* ?????????SpEL: #id:参数id的值 ?#a0 #p0 #root.args[0]
?????* ?????keyGenerator:key生成器;可以指定key生成器组件id;
?????* ?????????注:keyGenerator和key只能二选一
?????* ?????cacheManager:指定缓存管理器
?????* ?????cacheResolver:指定获取解析器
?????* ?????condition:指定符合条件情况下缓存
?????* ?????unless:否定缓存;当unless指定条件为true时,方法返回值不会被缓存;可以获取结果进行判断
?????* ?????sync:是否使用异步模式
?????*/
????//cacheNames = "emp":
????//condition = "#id>0":只有当id>0的时候再进行缓存
????//condition = "#a0>1":只有当第一个参数>1时候才进行缓存
????//unless = "#result==null":当返回结果为空时不进行缓存
????//unless = "#a0==2":如果第一个参数的结果为2,则结果不缓存
????//key = "#root.methodName+'['+#id+']'"
????//keyGenerator = "myKeyGenerator":自定义key
????@Cacheable(cacheNames = "emp"/*,condition = "#a0>1",unless = "#a0==2"*/)
????public Employee getEmp(Integer id){
????????System.out.println("查询"+id+"号员工");
????????Employee emp = employeeMapper.getEmpById(id);
????????return emp;
????}
?
????/**
?????* ?@CachePut:调用方法同时更新缓存数据
?????* ?修改数据库某个数据 同时更新缓存
?????*
?????* ?运行时间:
?????* ???1.先调用方法
?????* ???2.将方法的结果缓存起来
?????*
?????* ?测试步骤:
?????* ???1.查询1号员工;查询到的结果会放在缓存中 key:1 value:lastName:张三
?????* ???2.查询结果照旧
?????* ???3.更新1号员工信息[emp?id=1&lastName=zhangs&gender=0];将方法的返回值也放进缓存中 key:传入的employee对象 值:返回的employee对象
?????* ???4.查询1号员工;查询结果为未更新前的数据[1号员工的信息没有在缓存中更新]
?????* ?????key = "#employee.id":使用传入参数的员工id进行更新
?????* ?????key = "#result.id":使用返回后的id
?????* ?????注:@Cacheable的key是不能够使用#result
?????*/
????@CachePut(value = "emp",key = "#result.id")
????public Employee updateEmp(Employee employee){
????????System.out.println("update" + employee);
????????employeeMapper.updateEmp(employee);
????????return employee;
????}
?
????/**
?????* ?@CacheEvict:缓存清除
?????*/
????//key = "#id":指定key删除缓存
????//allEntries = true:删除缓存中所有数据 默认参数为false
????//beforeInvocation=false:缓存的清除是否在方法之前执行 默认是false,即清除缓存操作在方法执行之后执行 如果方法出现异常缓存就不会清除
????//beforeInvocation = true:清除缓存操作在方法执行之前执行 如果方法出现异常缓存也会清除
????@CacheEvict(value = "emp"/*,key = "#id"*//*,allEntries = true*/,beforeInvocation = true)
????public void deleteEmp(Integer id){
????????System.out.println("delete"+id);
// ???????employeeMapper.deleteEmpById(id);
????????int i = 10/0;
????}
?
????@Caching(
????????cacheable = ?{
????????????????@Cacheable(value="emp",key="#lastName")
????????},
????????put = {
??????????????@CachePut(value = "emp",key = "#result.id"),
??????????????@CachePut(value = "emp",key = "#result.email")
????????}
????)
????public Employee getEmpByLastName(String lastName){
????????return employeeMapper.getEmpByLastName(lastName);
????}
}
|