缓存-Spring Cache 缓存抽象

缓存-Spring Cache 缓存抽象

Spring从版本3.1开始提供非侵入的将Cache集成到Spring应用的方式。Spring Cache提供Cache的统一抽象,支持集成各种不同的缓存解决方案。从4.1版本开始,提供了注解和更多的定制参数。

Spring Cache 抽象提供了对Java方法的缓存,使用Spring Cache缓存,当方法调用使用相同的参数,调用结果被缓存下来,当方法被再次调用时将直接返回参数结果。

关键类和接口

Cache

org.springframework.cache.Cache 提供Spring框架中使用的Cache的统一抽象功能, 具体的实现类使用实际的缓存解决方案。

  • NoOpCache: 空缓存,没有实际的缓存实现
  • EhCacheCache: 使用EhCache缓存方案。
  • CaffeineCache: 使用Java CaffeineCache。Caffeine提出了一种更高效的近似LFU准入策略的缓存结构TinyLFU及其变种W-TinyLFU,借鉴Guava Cache的设计经验,是一款功能强大,性能更优本地缓存。
  • JCacheCache: Javax Cache 标准接口,类似于Spring Cache的 JavaJ JSR缓存规范。
  • ConcurrentMapCache: 使用ConccrentMap的缓存实现。
  • TransactionAwareCacheDecorator: 识别Spring 事务的缓存实现装饰模式,只要当事务提交时才触发缓存的更新。

CacheManager

org.springframework.cache.CacheManager:Spring cache 管理API。不同的CacheManager实现提供对相应Cache实现缓存的管理,通过管理API Cache getCache(String name);方法对外提供。

CacheResolver

org.springframework.cache.interceptor.CacheResolver 方法调用拦截使用来获取Cache实现的Resolver,通常使用相应的CacheManager实现类来获取Cache。

KeyGenerator

org.springframework.cache.interceptor. KeyGenerator:缓存中Key的生成实现。默认的key生成器:org.springframework.cache.interceptor.SimpleKeyGenerator 类

  1. 方法没有参数则使用SimpleKey.EMPTY

  2. 方法只有一个参数:key=唯一参数

  3. 方法有多个参数:SimpleKey(params)

可以通过实现org.springframework.cache.interceptor.KeyGenerator接口定制key生成器。

使用Spring Cache

启用Spring Cache

@Configuration

@EnableCaching

注解使用

**@Cacheable:**作用于方法之上,配置方法缓存

@Cacheable("cacheName"): 指定用于缓存结果的缓存名称,当指定多个名称时,方法调用将在多个缓存中查找相同参数的方法调用,命中即返回。

Cache 的key

指定KeyGenerator:

@Cacheable(cacheNames="XXX", keyGenerator="myKeyGenerator")。

通过SpEL指定key

@Cacheable(cacheNames="books", key="#isbn")

public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@CachePut: @CachePut指定的方法不影响方法的执行,方法执行结果将用于更新缓存。@CachePut支持同@Cacheable一样的配置。

示例:

@CachePut(cacheNames="book", key="#isbn")

public Book updateBook(ISBN isbn, BookDescriptor descriptor)

**@CacheEvict:**触发缓存清理陈旧或无用的数据。可以配置指定数据的清理或Cache范围的清理。

示例:

@CacheEvict(cacheNames="books", allEntries=true)

public void loadBooks(InputStream batch)

@Caching: 在一个方法上指定触发缓存的多个操作。

示例:

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })

public Book importBooks(String deposit, Date date)

**@CacheConfig:**以上的注解都是方法级别的注解,@CacheConfig提供类级别的公共配置,该类下的方法级别配置如无指定则使用类级别上的@CacheConfig。

实现方式

Spring AOP

使用 Spring AOP切面实现Cache相关方法的拦截获取缓存和Cache请求的处理

  1. 配置切面: 所有所有类和所有方法都进行拦截

org.springframework.cache.interceptor.CacheProxyFactoryBean

相关代码:

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| private Pointcut pointcut = Pointcut.TRUE; protected Object createMainInterceptor() { this.cacheInterceptor.afterPropertiesSet(); return new DefaultPointcutAdvisor(this.pointcut, this.cacheInterceptor); } |

  1. org.springframework.cache.interceptor.CacheInterceptor 实现

org.springframework.cache.interceptor.MethodInterceptor接口,

CacheAspectSupport.execute方法是Spring Cache核心处理流程,下面是主要流程的部分代码解析:

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 处理CacheEvict请求 processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT); // 从缓存中查询是否存在缓存 Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)); // 如未命中,生成CachePut请求:缓存条件满足 List<CachePutRequest> cachePutRequests = new ArrayList<>(); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests); } Object cacheValue; Object returnValue; if (cacheHit != null && !hasCachePut(contexts)) { // 缓存命中,并且没有Put需求,返回缓存值 cacheValue = cacheHit.get(); returnValue = wrapCacheValue(method, cacheValue); } else { // 未命中,调用对象,获取可缓存值 returnValue = invokeOperation(invoker); cacheValue = unwrapReturnValue(returnValue); } // 检查是否存在CachePut请求 collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests); // 缓存更新 for (CachePutRequest cachePutRequest : cachePutRequests) { cachePutRequest.apply(cacheValue); } // 处理缓存Evicts请求 rocessCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue); return returnValue; } |

相关推荐
麦兜*28 分钟前
MongoDB 6.0 新特性解读:时间序列集合与加密查询
数据库·spring boot·mongodb·spring·spring cloud·系统架构
a5876931 分钟前
消息队列(MQ)初级入门:详解RabbitMQ与Kafka
java·分布式·microsoft·面试·kafka·rabbitmq
考虑考虑35 分钟前
Postgerssql格式化时间
数据库·后端·postgresql
千里码aicood43 分钟前
【springboot+vue】党员党建活动管理平台(源码+文档+调试+基础修改+答疑)
java·数据库·spring boot
Chan161 小时前
【智能协同云图库】基于统一接口架构构建多维度分析功能、结合 ECharts 可视化与权限校验实现用户 / 管理员图库统计、通过 SQL 优化与流式处理提升数据
java·spring boot·后端·sql·spring·intellij-idea·echarts
先做个垃圾出来………1 小时前
差分数组(Difference Array)
java·数据结构·算法
库库林_沙琪马1 小时前
REST接口幂等设计深度解析
spring boot·后端
BillKu1 小时前
Java核心概念详解:JVM、JRE、JDK、Java SE、Java EE (Jakarta EE)
java·jvm·jdk·java ee·jre·java se·jakarta ee
IT_陈寒1 小时前
Redis性能提升50%的7个关键优化策略,90%开发者都不知道第5点!
前端·人工智能·后端
智商偏低1 小时前
ASP.NET Core 身份验证概述
后端·asp.net