缓存抽象
从版本3.1开始,Spring框架提供了对现有Spring应用程序透明地添加缓存的支持。类似于事务支持,缓存抽象允许以最小的代码影响来一致地使用各种缓存解决方案。
在Spring Framework 4.1中,缓存抽象得到了显著扩展,支持JSR-107注解以及更多的自定义选项。
部分总结
📄️ 理解缓存抽象
“缓冲区(buffer)”和“缓存(cache)”这两个术语经常被交替使用。然而需要注意的是,它们实际上代表不同的概念。传统上,缓冲区被用作快速处理单元与慢速处理单元之间的临时数据存储媒介。由于一方需要等待另一方(这会影响处理性能),缓冲区通过允许数据以整块的形式一次性传输来缓解这一问题,而不是分段传输。数据从缓冲区中只读写一次。此外,至少有一方能够看到这个缓冲区的存在。
📄️ 基于声明式注解的缓存
对于缓存声明,Spring的缓存抽象提供了一组Java注解:
📄️ JCache(JSR-107)注解
从4.1版本开始,Spring的缓存抽象全面支持JCache标准(JSR-107)注解:@CacheResult、@CachePut、@CacheRemove和@CacheRemoveAll,以及相关的@CacheDefaults、@CacheKey和@CacheValue注解。即使您没有将缓存存储迁移到JSR-107标准,也可以使用这些注解。Spring的内部实现利用了其缓存抽象,并提供了符合该规范的默认CacheResolver和KeyGenerator实现。换句话说,如果您已经在使用Spring的缓存抽象,那么您可以切换到这些标准注解,而无需更改您的缓存存储(或相关配置)。
📄️ 基于声明性XML的缓存
如果无法使用注释(可能是由于无法访问源代码或没有外部代码),你可以使用XML来进行声明式缓存。因此,与其为方法添加缓存注释,不如在外部指定目标方法和缓存指令(类似于声明式事务管理的做法)。上一节中的示例可以转换为以下示例:
📄️ 配置缓存存储
缓存抽象提供了几种存储集成选项。要使用它们,你需要声明一个适当的CacheManager(一个控制和管理缓存实例的实体,可以用来检索这些缓存实例以进行存储)。
📄️ 插入不同的后端缓存
显然,市面上有很多缓存产品可以作为后备存储使用。对于那些不支持JSR-107规范的产品,你需要自己提供CacheManager和Cache实现。这听起来可能比较复杂,但实际上这些类通常是简单的适配器,它们将缓存抽象框架映射到存储API之上,就像Caffeine类所做的那样。大多数CacheManager类可以使用org.springframework.cache.support包中的类(例如AbstractCacheManager,它负责处理样板代码,只需完成实际的映射工作即可)。
📄️ 如何设置TTL/TTI/驱逐策略/XXX功能?
直接通过你的缓存提供者。缓存抽象只是一种抽象,并非缓存实现。你使用的解决方案可能支持其他解决方案不支持的各种数据策略和不同的拓扑结构(例如,JDK的ConcurrentHashMap——在缓存抽象中暴露这一特性是没有用的,因为没有相应的底层支持)。此类功能应该通过底层缓存(在配置时)或其原生API来直接控制。