SpringBoot中Cache缓存解析

一、Cache缓存的作用

随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一。Spring 3开始提供了强大的基于注解的缓存支持,可以通过注解配置方式低侵入的给原有Spring应用增加缓存功能,提高数据访问性能。在Spring Boot中对于缓存的支持,提供了一系列的自动化配置,使我们可以非常方便的使用缓存。

1.核心接口

Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。
SpringBoot中Cache缓存解析_第1张图片

1.spring缓存抽象

CachingProvider定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可 以在运行期访问多个CachingProvider。
CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache 存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个 CacheManager所拥有。
Entry是一个存储在Cache中的key-value对。
Expiry 每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期 的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。

二、缓存注解

Cache 缓存接口,定义缓存操作
@Cacheable 主要针对方法配置,能够根据方法的参数对其结果进行缓存
@CacheEvict 清除缓存
@CachePut 保证方法被调用,将缓存保存起来
@EnableCaching 启动类中开启基于注解的缓存
Cache注解中参数 参数 解析 源码注解
@value 缓存的名称,在 spring 配置文件中定义,必须指定 至少一个。 源码注释: Names of the caches in which method invocation results are stored.Names may be used to determine the target cache (or caches), matching the qualifier value or bean name of a specific bean definition.
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达 式编写,如果不指定,则缺省按照方法的所有参数 进行组合 Spring Expression Language (SpEL) expression for computing the key dynamically Default is {@code “”}, meaning all method parameters are considered as a key, unless a custom {@link #keyGenerator} has been configured.The SpEL expression evaluates against a dedicated context that provides the following meta-data
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存/清除缓存,在 调用方法之前之后都能判断 Spring Expression Language (SpEL) expression used for making the method * caching conditional. *

Default is {@code “”}, meaning the method result is always cached. *

The SpEL expression evaluates against a dedicated context that provides the * following meta-data

三、操作流程

1.引入依赖

SpringBoot中Cache缓存解析_第2张图片

2.@EnableCaching开启缓存

SpringBoot中Cache缓存解析_第3张图片

2.controllerSpringBoot中Cache缓存解析_第4张图片

3.service

SpringBoot中Cache缓存解析_第5张图片

3.serviceImpl

SpringBoot中Cache缓存解析_第6张图片
SpringBoot中Cache缓存解析_第7张图片

 /*1. @Cacheable的几个属性详解:
 @Service
@CacheConfig(cacheNames = "person") //将cacheNames抽取出来
public class PersonService {
@Autowired
PersonDao personDao;
  *       cacheNames/value:指定缓存组件的名字
  *       key:缓存数据使用的key,可以用它来指定。默认使用方法参数的值,一般不需要指定
  *       keyGenerator:作用和key一样,二选一
  *       cacheManager和cacheResolver作用相同:指定缓存管理器,二选一
  *       condition:指定符合条件才缓存,比如:condition="#id>3"
  *                   也就是说传入的参数id>3才缓存数据
  *      unless:否定缓存,当unless为true时不缓存,可以获取方法结果进行判断
  *      sync:是否使用异步模式*/
 //@Cacheable(cacheNames= "person")
 //@Cacheable(cacheNames= "person",key="#id",condition="#id>3")
 @Cacheable(key="#id")
 public Person queryPersonById(Integer id){
    System.out.println("查询"+id+"号员工信息");
    Person person=new Person();
    person.setId(id);
    return personDao.query(person);
}

/**
 * @CachePut:即调用方法,又更新缓存数据
 * 修改了数据库中的数据,同时又更新了缓存
 *
 *运行时机:
 * 1.先调用目标方法
 * 2.将目标方法返回的结果缓存起来
 *
 * 测试步骤:
 * 1.查询1号的个人信息
 * 2.以后查询还是之前的结果
 * 3.更新1号的个人信息
 * 4.查询一号员工返回的结果是什么?
 *     应该是更新后的员工
 *     但只更新了数据库,但没有更新缓存是什么原因?
 * 5.如何解决缓存和数据库同步更新?
 * 这样写:@CachePut(cacheNames = "person",key = "#person.id")
 *         @CachePut(cacheNames = "person",key = "#result.id")
 */
@CachePut(key = "#result.id")
public Person updatePerson(Person person){
    System.out.println("修改"+person.getId()+"号员工信息");
    personDao.update(person);
    return person;

}
/**
 * @CacheEvict:清除缓存
 *    1.key:指定要清除缓存中的某条数据
 *    2.allEntries=true:删除缓存中的所有数据
 *    beforeInvocation=false:默认是在方法之后执行清除缓存
 *    3.beforeInvocation=true:现在是在方法执行之前执行清除缓存,
 *                          作用是:只清除缓存、不删除数据库数据
 */
//@CacheEvict(cacheNames = "person",key = "#id")
@CacheEvict(cacheNames = "person",allEntries=true)
public void deletePerson(Integer id){
    System.out.println("删除"+id+"号个人信息");
    //删除数据库数据的同时删除缓存数据
    //personDao.delete(id);

    /**
     * beforeInvocation=true
     * 使用在方法之前执行的好处:
     * 1.如果方法出现异常,缓存依旧会被删除
     */
    //int a=1/0;
}

/**
 *   @Caching是 @Cacheable、@CachePut、@CacheEvict注解的组合
 *   以下注解的含义:
 *   1.当使用指定名字查询数据库后,数据保存到缓存
 *   2.现在使用id、age就会直接查询缓存,而不是查询数据库
 */
@Caching(
        cacheable = {@Cacheable(key="#name")},
        put={ @CachePut(key = "#result.id"),
              @CachePut(key = "#result.age")
            }
)
public Person queryPersonByName(String name){
    System.out.println("查询的姓名:"+name);
    return personDao.queryByName(name);
}

}

你可能感兴趣的:(spring)