SpringBoot的默认缓存

1、JSR107(技术复杂性较大)

Java Caching定义了5个核心接口:Entry、Expiry、Cache、CachingProvider和CacheManager
(1)CacheProvider:定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以再运行期访问多个CacheProvider。
(2)CacheManager:定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CacheProvider所拥有。
(3)Cache:是一个类似Map的数据结构并临时存储以key为索引的值。一个Cache仅被一个CacheManager所拥有。
(4)Entry:是一个存储在Cache中的key-value对。
(5)Expiry:没一个存储在Cache中的条目有一个定义的有效期。一旦超过这个期限,条目为过期状态,将不可在进行访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。
在这里插入图片描述

2、Spring缓存抽象

(1)使用Spring缓存抽象时我们需要关注以下两点:
A、确定方法需要被缓存以及它们的缓存策略
B、从缓存中读取之前缓存存储的数据
(2)几个重要的概念&缓存注解

Cache缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等
CacheManager缓存管理器,管理各种缓存(Cache)组件
@Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存(查询 )
@CacheEvict清空缓存(删除)
@CachePut保证方法被调用,又希望结果被缓存(更新)
@EnableCaching开启基于注解的缓存
keyGenerator缓存数据时key生成策略
Serialize缓存数据时value序列化策略

(2)SpringBoot整合Cache
A、引入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

B、开启基于注解的缓存@EnableCaching

@MapperScan("com.chen.cache.mapper")
@SpringBootApplication
@EnableCaching
public class Springboot01CacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot01CacheApplication.class, args);
    }
}

C、标注缓存注解即可
a、@Cacheable

    /***
     * 将方法的运行结果进行缓存;以后在查询相同的数据,直接从缓存中获取,不用调用方法
     *
     * CacheManager管理多个Cache组件,对缓存的真正的CURD操作在Cache组件中,且每一个缓存组件都有自己的名字;
     * @Cacheable 的几个属性:
     *      CacheNames/value:指定缓存组件的名字
     *      key:缓存数据使用的key;默认使用方法参数值(id)-方法的返回值(Employee)
     *      keyGenerator:key的生成器;(key和keyGenerator不能同时指定)
     *      cacheManager:指定缓存管理器、cacheResolver:指定缓存解析器(两者二选一)
     *      condition:符合指定条件下才缓存;例:condition="#id>0"
     *      unless:否定缓存;为true不缓存
     *      sync:是否使用异步模式 
     *    ☆3、@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存。
     *          若没查到,则运行方法并将结果放入缓存。以后再来调用可以直接使用缓存中的数据
     * @param id
     * @return
     */
    @Cacheable(cacheNames = "emp")
	public Employee getEmpById(Integer id){
    	System.out.println("查询"+id+"号员工!");
    	return employeeMapper.getEmployeeById(id);
 	}

注: 其中@Cacheable的属性值的设定可以使用SpEL表达式:
在这里插入图片描述
b、@CachePut

	/***
     * @CachePut:既调用方法,又更新缓存数据
     *  修改数据库某个数据,同时更新缓存
     *
     *  运行时机:
     *      1、先调用目标方法
     *      2、将目标方法的结果缓存起来
     *  测试步骤:
     *      1、查询1号员工,结果放到缓存中
     *             key=1; value=employee对象
     *      2、更新1号员工
     *             将方法的返回值也放进缓存
     *      3、如果需要再次查询1号员工不需要进数据库直接获得更新后的数据,那么更新员工的时候需要指定跟查询员工时一样的key
     *             key="#employee.id"  使用传入参数的员工id
     *             key="#result.id"    使用返回值的id
     */
    @CachePut(value = "emp",key = "#result.id")
    public Employee updateEmp(Employee employee){
        System.out.println("updateEmp:"+employee);
        employeeMapper.updateEmp(employee);
        return employee;
    }

c、@CacheEvict

/***
 * @CacheEvict:清除缓存
 *  key指定要删除哪个Cache
 *  allEntries = true:指定清除这个缓存中所有数据
 *  beforeInvocation:默认为false表示缓存的清除是否在方法之后执行,如果出现异常则不会清除
 */
@CacheEvict(value = "emp",key = "#id")
public int delteEmp(Integer id){
    System.out.println("deleteEmp:"+id);
    //employeeMapper.deleteEmp(id);
    return id;
}

d、@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){
        System.out.println("查询名为:"+lastName+"的员工!");
        return employeeMapper.getEmployeeByLastName(lastName);
    }

注:当通过lastName查询之后利用@Cacheable将结果添加到缓存中,另外还利用@CachePut在缓存中添加key为id和email的Cache,所以当用id或者email查询时会直接从缓存中取,但是通过lastName查询还是会查询数据库,因为@CachePut是先执行方法致使查询lastName时需要查询数据库。

d、@CacheConfig: 抽取缓存的公共配置

@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {
	...
	...
	...
    @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){
        System.out.println("查询名为:"+lastName+"的员工!");
        return employeeMapper.getEmployeeByLastName(lastName);
    }
}

原理:

1、自动配置类:CacheAutoConfiguration
2、缓存的配置类默认生效:SimpleCacheConfiguration->给容器中注册了一个ConcurrentMapCacheManager->可以获取和创建ConcurrentMapCache类型的缓存组件->将数据保存在ConcurrentMap<Object,Object>中;
运行流程:
1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(ConcurrentManager先获取相应的缓存),第一次获取缓存如果没有获取到就会自动创建
2、去Cache中使用key(默认为传入的参数)查找缓存的内容
key是按照策略生成的;使用keyGenerator生成key,默认使用SimpleKeyGenerator生成key
SimpleKeyGenerator生成key的默认策略:
* 如果没有参数:key = new SimpleKey();
* 如果有一个参数:key = 参数值
* 如果与多个参数:key = new SimpleKey(params)
3、没有查到缓存就会调用目标方法去数据库获取,并将目标方法返回的结果放进缓存中
总结:
1、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2、key使用keyGenerator生成,默认是SimpleKeyGenerator

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值