java中Cache缓存

1.JSR107

LRU java实现 缓存 java 加缓存_缓存

缓存的整体架构:

LRU java实现 缓存 java 加缓存_数据_02

2.SpringBoot的缓存抽象

LRU java实现 缓存 java 加缓存_数据_03

几个重要概念以及缓存注解

LRU java实现 缓存 java 加缓存_java_04

其中想要使用缓存直接,就必须开启**@EnableCaching**注解

开启缓存注解的步骤:

作为Spring框架的核心功能之缓存注解,该功能也继承了Spring这个优良特性,使它生效只需要轻松两步:

1.配置类上开启缓存注解支持:@EnableCaching

2.向容器内至少放置一个CacheManager类型的Bean

这样就可以开工使用Spring强大的缓存注解功能了。

@EnableCaching
@Configuration
public class CacheConfig {
    @Bean
    public ConcurrentMapCacheManager cacheManager() {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
        //cacheManager.setStoreByValue(true); //true表示缓存一份副本,否则缓存引用
        return cacheManager;
    }
}

@Cacheable

@Cacheable  //对方法结果能够放入缓存中,比如若根据id查找user时,会将返回的结果放进换缓存中,如果下一次再进行相同操作,便不会调用方法,而是直接从缓存中获取结果值
public User getUser(Integer id);

@CacheEvict:能够清空缓存

@CachePut

@CachePut  //能够更新缓存的值,加上这个注解每次更新缓存的时候都会调用这个方法,然后将更新的结果返回到缓存中
public User updateUser(User user);

实例:

@CacheConfig(cacheNames = "emp")  //抽取缓存的公共配置
@Service
public class EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;

    /*
     * 将方法的运行结果进行缓存,以后再要相同的数据就直接从缓存取,不用再次调用这个方法
     * CacheManager管理多个cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一的名字
     * 几个属性:
     *       cacheName/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
     *       key:缓存数据使用的key;可以用它来指定,若果不指定,默认使用方法参数的值(比如id传入1:则 key-value为   1-方法的返回值)
     *           编写SqEL:#id:参数id的值   #a0  #p0 #root.args[0]   这几个效果都是一样的,取出第一个参数,作为key
     *           key = "#id"
     *       keyGenerator:key的生成器;可以自己指定key的生成器的组件id
     *       key/keyGenerator二选一使用
     *       CacheManager:指定缓存管理器  或者使用CacheResolver缓存解析器
     *       condition:指定符合条件的情况下才缓存;
     *           condition = "#id>0"
     *       unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存,可以获取到结果进行判断
     *           unless = "#result==null"
     *       sync:是否使用异步模式
     *原理:
     *   1.自动配置类:CacheAutoConfiguration
     *   2.缓存的配置类
     *   。。。。。。
     *   3.哪个配置类默认生效:SimpleCacheConfiguration
     *   4.给容器中注册了一个CacheManager:ConcurrentMapCacheManager
     *   5.可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中
     *
     *   运行的流程:
     *       @Cacheable:
     *       1.方法运行之前,先去插叙Cache(缓存组件),按照cacheNames指定的名字获取;
     *           (CacheManager先获取相应的缓存),第一次获取缓存如果没有找到指定的Cache组件,会自动创建出来
     *       2.去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
     *         key是按照某种策略生成的;默认是使用KeyGenerator生成的,默认使用SimpleKeyGenerator生成key
     *           SimpleKeyGenerator生成策略:
     *               如果方法没有参数,key=new SimpleKey()
     *               方法有一个参数,key=参数的值
     *               方法有多个参数,key=new SimpleKey(params)
     *       3.没有查到缓存就调用目标方法;
     *       4.将目标方法返回到结果,放进缓存中
     *
     *       @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,如果有,就从缓存中获取不会调用方法,
     *       如果没有,就调用这个方法并将方法结果放到缓存中,以后再来调用就可以直接使用缓存中的数据。
     *
     *       核心:
     *           1)、使用CacheManager【默认:ConcurrentMapCacheManager】按照名字得到Cache【默认:ConcurrentMapCache】组件
     *           2)、key使用KeyGenerator生成的,默认是SimpleKeyGenerator
     * */
    @Cacheable(cacheNames = "emp"/*, keyGenerator = "myKeyGenerator"*/)
    public Employee getEmp(Integer id) {
        System.out.println("查询" + id + "号员工");
        Employee emp = employeeMapper.getEmployeeById(id);
        return emp;
    }

    @Cacheable(/*cacheNames = "emp",*/key = "#employee.id")
    public Employee insertEmp(Employee employee){
        System.out.println("InsertEmp:"+employee.getId());
        employeeMapper.insertEmployee(employee);
        return employee;
    }


    /*
     * @CachePut:既调用方法,又更新缓存数据;同步更新缓存
     * 修改了数据库的某个数据,同时更新缓存;
     * 运行时机:
     *   1、先调用目标方法
     *   2、将目标方法的结果缓存起立
     *
     * 测试步骤:
     *   1、查询1号员工;查到的结果会放到缓存中
     *   2、以后查询还是之前的结果
     *   3、更新1号员工:【lastName=zhangsan; gender=0】
     *       将方法的返回值也放进了缓存:
     *           key:传入的对象  值:返回的employee对象;
     *   4、查询1号员工?
     * */
    @CachePut(/*value = "emp",*/ key = "#result.id")
    public Employee updataEmp(Employee employee) {
        System.out.println("updateEmp:" + employee);
        employeeMapper.updataEmployee(employee);
        return employee;
    }

    /*
    * @CacheEvict:缓存清除
    *   key:指定要清除的数据
    *   allEntries=true:默认为false,设置为true,当删除缓存数据时,便会删除指定缓存中的所有数据
    *   beforeInvocation(布尔型):缓存的清除是否在方法之前执行
    *       false(默认值):代表在方法执行之后执行;如果该方法运行时出现异常缓存就不会清除
    *       true:代表在方法执行之前执行;如果该方法运行时出现异常,缓存也会被清除
    * */
    @CacheEvict(/*value = "emp",*/key = "#id")
    public void deleteEmp(Integer id){
        System.out.println("deleteEmp:"+id);
//        employeeMapper.deleteEmployeeById(id);
    }

    //@Caching定义复杂的缓存规则
    @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);
    }
}