1.SpringBoot的缓存缓存Cacheable缓存注解
2.SpringBoot 缓存之 @Cacheable 详细介绍
3.Springboot应用缓存实践之:Ehcache加持
4.基于Spring Cache实现二级缓存(Caffeine+Redis)
5.Spring三级缓存
6.Spring中@Cacheable、@CacheEvict以及其他缓存相关注解的源码原理实用介绍
SpringBoot的Cacheable缓存注解
为了提升应用程序的性能,我们在处理大量数据读取和写入操作时,缓存缓存往往会采用缓存技术。源码原理Spring Boot 提供了一套高效便捷的缓存缓存缓存解决方案,支持将数据缓存至 Redis 源码原理无缝拼图源码中。
在 Spring Boot 中,缓存缓存我们只需在方法上添加相应的源码原理注解即可实现缓存功能。
首先,缓存缓存您需要在项目中引入 Redis 源码原理依赖。以下是缓存缓存在 pom.xml 中添加 Redis 依赖的示例:
引入 Redis 依赖后,接下来需要配置 Redis 源码原理相关信息。以下是缓存缓存一个 Redis 配置的示例:
在此配置中,host 和 port 属性分别指定了 Redis 源码原理服务器的主机名和端口号,password 属性用于指定 Redis 缓存缓存服务器的密码(如果有的话),而 database 属性则指定了 Redis 服务器使用的数据库编号。
Redis 默认序列化器为 JdkSerializationRedisSerializer,但通常我们更倾向于使用 StringRedisSerializer 或 Jackson2JsonRedisSerializer 将缓存值序列化为字符串或 JSON 格式。以下是一个自定义序列化器的示例配置:
在这个示例中,我们通过自定义 Bean 配置了 RedisTemplate,使用 StringRedisSerializer 序列化 Redis 键,并使用 Jackson2JsonRedisSerializer 序列化 Redis 值为 JSON 格式。
使用 Cacheable 注解来标记需要进行缓存的方法。以下是一个带有 Cacheable 注解的示例方法:
在这个例子中,@Cacheable 注解用于标记 getUserById 方法,value 属性用于指定缓存的存储区域名称。由于我们正在使用 Redis 作为缓存,因此 Redis 中的 key 将由 Cacheable 注解中的 key 属性指定。在此示例中,key 属性设置为 "#id",这意味着我们将使用方法参数 id 作为 Redis 缓存的键。
在某些情况下,我们需要以多个参数作为 key 来缓存数据。此时,我们可以使用表达式语言(SpEL)来设置多个参数,如下所示:
在这个示例中,我们使用了表达式语言(SpEL)将 id 和 name 两个参数组合成了一个 Redis 缓存键。
缓存的有效期对缓存的性能和可靠性有很大影响。可以使用 @Cacheable 注解上的 expire 属性来设置缓存的过期时间。以下是一个设置缓存时效的示例:
在此示例中,我们添加了名为 expire 的属性,该属性用于指定缓存的cci 背离 源码过期时间(以秒为单位)。在此示例中,我们设置了缓存过期时间为 秒,即 分钟。
有时候,我们需要清除 Redis 缓存中的某些数据,以便在下一次访问时重建缓存。在 Spring Boot 中,可以使用 @CacheEvict 注解来清除 Redis 缓存中的数据。以下是一个使用 @CacheEvict 注解的示例:
在这个例子中,我们添加了删除单个用户和删除所有用户的方法,使用 @CacheEvict 注解来删除 Redis 缓存中的相应数据。请注意,我们设置了 allEntries 属性为 true,以删除所有缓存中的数据。
有时候,我们需要在特定条件下才进行缓存操作。例如,只有当用户年龄大于 岁时才进行缓存。在 Spring Boot 中,可以使用 @Cacheable、@CachePut 和 @CacheEvict 注解上的 condition 属性来设置缓存条件。以下是一个使用 condition 属性的示例:
在这个例子中,我们添加了一个名为 condition 的属性,该属性用于指定缓存的条件。在此示例中,我们将 condition 属性设置为 "#age > ",这意味着只有当 age 大于 时,才进行缓存操作。
在实际使用中,应用程序缓存数据的管理也是非常重要的。Spring Boot 提供了一个名为 CacheManager 的接口,您可以使用它来创建并管理缓存对象。以下是一个使用 CacheManager 的示例:
在这个示例中,我们创建了一个名为 CacheConfig 的配置类,并使用 @EnableCaching 注解来开启缓存支持。然后,我们通过实现 CachingConfigurerSupport 接口,覆盖 cacheManager 方法,创建了一个 RedisCacheManager 对象,并将其返回。在此 RedisCacheManager 中,hidistro源码下载我们使用默认的 RedisCacheConfiguration 进行了一些配置,例如设置缓存的过期时间,同时指定了 Redis 的连接信息。
本文介绍了如何在 Spring Boot 应用程序中使用 Redis 进行缓存,包括配置 RedisTemplate、使用 Cacheable 注解、设置缓存有效期、使用 @CacheEvict 清除缓存数据以及使用 CacheManager 管理缓存等。
SpringBoot 缓存之 @Cacheable 详细介绍
Spring Boot 缓存机制,特别是 @Cacheable 注解,为开发者提供了高效的数据缓存功能。Spring Boot 从 3.1 版本开始,引入了对缓存的支持,通过 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口统一管理不同缓存技术,并利用 JCache(JSR-)注解简化了开发过程。其核心思想是,每次调用带缓存功能的方法时,Spring 会检查指定参数的目标方法是否已被调用过,若有则直接从缓存中获取结果,无则调用方法并缓存结果后返回给用户。这样,下次调用时,直接从缓存中获取结果,显著提升性能。
@Cacheable 注解用于启用缓存功能,实现步骤包括开启基于注解的缓存和标注缓存注解。开启缓存通常在 SpringBoot 主启动类上通过 @EnableCaching 标注实现。标注缓存注解时,可选择使用@Cacheable,它将方法的返回结果缓存起来,后续查询相同数据时,直接从缓存中获取,无需再次调用方法。
在使用 @Cacheable 注解时,有多个常用属性可以灵活配置。cacheNames 属性用于指定缓存组件名称,指定存储数据的缓存名称,支持多个缓存。key 属性用于设置缓存数据时使用的键,默认使用方法参数值,也可通过 SP EL 表达式编写。咕咚运动源码keyGenerator 属性允许自定义键生成器,通过生成器来创建键,确保缓存中的键生成遵循自定义规则。通常情况下,key 和 keyGenerator 二者中选择其一进行配置。
condition 属性用于判断是否缓存数据,实现动态缓存。unless 属性则在指定条件下禁止缓存,当 unless 指定条件为真时,方法的返回值不会被缓存。sync 属性控制缓存操作的同步性,默认以同步方式将方法返回结果存入缓存。
SP EL(Spring Expression Language)允许在编写 key 时使用元数据,这为复杂数据结构和动态生成键提供了便利。在使用 SP EL 编写 key 时,可以引用方法参数、方法返回值等,实现灵活、动态的缓存键生成。通过合理配置和利用 SP EL,开发者可以有效地优化应用性能,提高数据访问效率。
Springboot应用缓存实践之:Ehcache加持
本文共 字,阅读大约需要 3分钟!代码在文尾处!
在如今高并发的互联网应用中,缓存的地位举足轻重,对提升程序性能帮助不小。而3.x开始的 Spring也引入了对 Cache的支持,那对于如今发展得如火如荼的 Spring Boot来说自然也是支持缓存特性的。当然 Spring Boot默认使用的是 SimpleCacheConfiguration,即使用ConcurrentMapCacheManager 来实现的缓存。但本文将讲述如何将 Ehcache缓存应用到Spring Boot应用中。
「Ehcache」 是一个基于Java实现的开源缓存管理库,提供了用内存、磁盘文件存储、以及分布式存储等多种灵活的管理方案。使用方式和原理都有点类似于 Spring事务管理,配合各项注解可以很容易的上手。
下文就上手来摸一摸它,结合对数据库的宠物展示源码操作,我们让 Ehcache作为本地缓存来看一下效果!
比如我这里准备了一张用户表,包含几条记录:
我们将通过模拟数据库的存取操作来看看 Ehcache缓存加入后的效果。
pom.xml 中添加如下依赖:
创建Ehcache的配置文件 ehcache.xml并置于项目 classpath下:
配置 application.properties编写操作数据库和 Ehcache缓存的业务代码
看得很明白了,我们在getUsersByName接口上添加了注解:@Cacheable。这是 Ehcache的使用注解之一,除此之外常用的还有 @CachePut和 @CacheEvit,分别简单介绍一下:
改造SpringBoot应用主类
主要是在启动类上通过 @EnableCaching注解来显式地开启 Ehcache缓存
最终完工的整个工程的结构如下:
通过多次向接口localhost/getusersbynamePOST数据来观察效果:
可以看到缓存的启用和失效时的效果(上文ehcache的配置文件中设置了缓存user的实效时间为s):
由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流! 本文实验代码在此
基于Spring Cache实现二级缓存(Caffeine+Redis)
在探索缓存优化之道时,硬编码使用缓存的方式显得不够优雅。面对查询效率的提升需求,我们通常会采用缓存策略。然而,这种方式在业务逻辑与缓存操作之间引入了不必要的耦合,导致代码的复杂性和维护成本上升。Spring Cache的引入,为这一问题提供了优雅的解决方案。
Spring Cache是Spring-context包提供的组件,允许通过注解方式使用缓存。它定义了标准接口,如Cache和CacheManager,使得缓存的管理与业务逻辑分离,提高代码的可读性和可维护性。
Spring Cache的核心接口包括Cache和CacheManager。Cache接口定义了缓存的基本操作,如存储、读取和清理;CacheManager接口则负责创建Cache实现bean,并提供基于缓存名进行隔离的功能。
在Spring Cache中,常用注解有@Cacheable、@CacheEvict、@CachePut和@Caching。@Cacheable用于查询数据的方法,@CacheEvict用于清除缓存,@CachePut用于更新缓存,而@Caching则允许在一个方法上配置多种注解。
为了进一步提升性能,我们引入了二级缓存的概念。一级缓存通常位于应用内部,如使用Caffeine作为高速缓存,而二级缓存则利用像Redis这样的远程存储。这种设计通过减少对远程缓存的频繁访问,显著降低了网络开销。
实现二级缓存时,需要考虑一致性、空值存储、缓存预热、存储数量上限、过期策略等关键问题。Caffeine作为高性能缓存库,提供了一种简洁的解决方案。它支持手动、同步加载和异步加载的写入策略,以及基于大小、时间或引用的缓存值清理策略。
统计信息的记录、高效的缓存淘汰算法、底层数据存储采用ConcurrentHashMap(结合了JDK8的优化)都是Caffeine的关键特性。LRU、LFU和FIFO等算法被用于缓存淘汰,其中W-TinyLFU算法结合了LRU和LFU的优点,以实现高命中率和低内存占用。
在实际应用中,结合Spring Cache与Caffeine实现二级缓存时,还需考虑分布式节点的一致性问题。通过Redis的订阅/发布功能,可以实现对数据更新和删除操作的跨节点通知,从而确保缓存的一致性。引入Redis缓存,不仅简化了节点间通信的复杂性,还避免了依赖额外组件。
为了集成Caffeine缓存,可通过Maven引入相关依赖包,并在配置文件(如application.yml)中添加二级缓存相关配置。在启动类上使用@EnableCaching注解启用缓存功能,最后在需要缓存的方法上添加@Cacheable注解即可。
Spring三级缓存
Spring框架采用三级缓存策略来巧妙地解决循环依赖问题,特别针对AOP代理对象的复杂场景。常规的一级缓存并不足以处理这种情况,因为循环依赖可能涉及AOP代理后的对象,而非原始对象。
二级缓存的引入是为了解决这个问题。当B和C依赖于A时,通过二级缓存存储A的代理对象,确保在创建B和C时不会重复创建A的代理,从而保持单例性。这种策略避免了在对象初始化后立即进行AOP操作,以遵循bean的生命周期。
然而,二级缓存的使用也有其挑战。它需要提前将AOP操作后的代理对象放入缓存,但这可能会干扰对象的初始化过程,因为AOP通常在对象初始化后执行后置处理。这意味着在设计三级缓存时,需要对Spring的源码有深入理解,特别是涉及这几个重要集合的部分:
1. 单例Bean获取的源码
总结来说,Spring的三级缓存策略通过精细的缓存管理,巧妙地处理了循环依赖问题,确保了bean的正确生命周期和性能优化。同时,理解源码中的关键集合和操作对实现这种策略至关重要。
Spring中@Cacheable、@CacheEvict以及其他缓存相关注解的实用介绍
缓存管理器是 Spring 应用程序中缓存机制的核心。它负责管理缓存数据,确保有效存储、检索和逐出条目。设置缓存管理器对于实现高效缓存至关重要。常用的缓存管理器如ConcurrentMapCacheManager、Hazelcast、Redis、EhCache 和 Caffeine,它们提供不同的性能和功能,以满足不同场景的需求。通过实现CacheManager接口,开发者可以创建自定义缓存管理器,以适应特定的应用需求。配置和调整缓存管理器参数,如缓存大小、失效时间等,可进一步优化性能。监控缓存的性能是确保缓存发挥作用而不成为瓶颈的重要步骤。
使用@Cacheable注释,开发者可以指示 Spring 将方法的返回值存储在指定的缓存中。这使得后续使用相同参数调用此方法时,可以从缓存中获取结果,而无需执行方法。此功能减少了计算负担,提高了应用程序性能。通过配置@CacheEvict注释,开发者可以确保在特定操作后缓存数据的更新。这确保了缓存数据与应用程序数据的一致性,避免了过时的信息。组合注释@Cacheable和@CacheEvict提供了更高级的缓存策略,支持根据具体场景的需求进行灵活配置。
Spring 提供了更高级的缓存注释和属性,如@CacheConfig、@CachePut 和@CacheResolver,以提供对缓存行为的更精细控制。@CacheConfig允许在类级别配置缓存策略,@CachePut用于在更新操作后更新缓存,而@CacheResolver用于解析缓存键和条件。密钥生成、自定义缓存条件等特性进一步增强了缓存的灵活性和适应性。最佳实践包括了解业务需求、选择合适的缓存类型、注意缓存粒度、动态缓存管理和优雅地处理缓存故障。通过遵循这些最佳实践,开发者可以最大限度地发挥缓存的优势,同时避免潜在的问题。
Spring 的缓存注释提供了强大而灵活的机制,用于优化应用程序性能。通过合理配置和使用这些注释,开发者可以实现响应能力的显著提升和可扩展性。然而,正确使用和监控缓存策略对于确保其性能优势的同时避免潜在问题至关重要。深入理解缓存机制,遵循最佳实践,定期测试和评估,以及保持文档更新,是确保 Spring 应用程序高效利用缓存的关键。
④优雅的缓存框架:SpringCache之多级缓存
多级缓存策略能够显著提升系统响应速度并减轻二级缓存压力。本文采用Redis作为二级缓存,Caffeine作为一级缓存,通过多级缓存的设计实现优化。
首先,进行多级缓存业务流程图的声明,并通过LocalCache注解对一级缓存进行管理。具体源码地址如下。
其次,自定义CaffeineRedisCache,进一步优化缓存性能。相关源码地址提供如下。
为了确保缓存机制的正确执行,自定义CacheResolver并将其注册为默认的cacheResolver。具体实现细节可参考以下源码链接。
在实际应用中,通过上述自定义缓存机制,能够有效地提升系统性能和用户体验。为了验证多级缓存优化效果,我们提供实战应用案例和源码。相关实战案例和源码如下链接。
实现多级缓存策略的完整源码如下:
后端代码:<a href="github.com/L1yp/van-tem...
前端代码:<a href="github.com/L1yp/van-tem...
欲加入交流群讨论更多技术内容,点击链接加入群聊: Van交流群
超级干货为什么spring一定要弄个三级缓存?
在深入探讨为什么Spring需要实现三级缓存之前,我们首先回顾Spring创建bean的流程。Spring在获取bean时会经历两到三层缓存的检查,这在处理循环依赖问题时尤其关键。
具体来说,Spring创建bean时,如果不存在循环依赖,通常只会使用到第一层缓存。但当存在循环依赖时,第二层和第三层缓存则发挥了重要作用。它们通过缓存对象工厂的返回结果来避免不必要的计算,提高效率。
以一个简单的demo为例,我们假设有两个接口及其实现类相互引用。当创建其中一个实现类时,Spring会先从第一层缓存中查找bean实例。如果没有找到,则可能进入第二或第三层缓存检查。若仍然未找到,Spring会调用对象工厂的`getObject`方法。该方法会先执行`getEarlyBeanReference`,如果返回新对象,则此对象会被缓存以供后续使用。这样,当其他依赖于当前bean的bean需要初始化时,可以避免重复计算,大大提高性能。
现在,让我们回到问题的核心:为什么Spring需要三级缓存?答案在于代理类的引入。代理类可能在bean的初始化过程中被创建,以实现诸如事务管理等功能。Spring通过三级缓存确保了代理类的正确引用,即使在处理循环依赖时也能保持一致。这使得在bean实例的创建和初始化之间建立了一层保护,确保了正确的依赖关系。
假设我们仅使用第一层缓存,那么在bean实例创建后,即使需要代理类,也无法确保在循环依赖场景下代理类的正确引用。引入第二层缓存,使得当对象工厂返回新对象时,该对象可以被缓存以供循环依赖的bean引用。第三层缓存则进一步确保了循环依赖场景下,代理类引用的一致性,防止了在初始化完成前代理类引用的混乱。
总的来说,三级缓存的设计并非为了代理类的存在,而是为了处理循环依赖时的复杂性。通过这一设计,Spring能够在提供循环依赖支持的同时,保持高性能和代码的可维护性。
若想进一步深入理解Spring源码,推荐查阅Spring源码深度解析专栏,其中详细解读了Spring的核心机制和源码细节,帮助开发者全面理解Spring框架。