⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/wodejiaAA/article/details/132989681 「家有娇妻张兔兔」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

Spring 提供了对缓存的支持,允许你将数据存储在缓存中以提高应用程序的性能。Spring 缓存抽象基于 Java Caching API,但提供了更简单的编程模型和更高级的功能。

Spring 集成缓存提供了一种方便的方式来使用缓存,从而提高应用程序的性能。Spring 缓存抽象提供了通用的缓存支持,并集成了常见的缓存解决方案。

缓存接口

Spring 的缓存 API 以注解方式提供。Spring缓存接口定义主要由org.springframework.cache.Cache和org.springframework.cache.CacheManager两个接口完成。

org.springframework.cache.Cache:这个接口代表一个缓存组件,Spring框架通过这个接口与缓存交互。它有几个重要的方法:

  • String getName(): 返回缓存的名称。
  • Object get(Object key, Class<?> type): 根据key获取缓存数据,如果数据不存在,返回null。
  • void put(Object key, Object value): 向缓存中添加数据。
  • void evict(Object key): 根据key移除缓存数据。
  • void clear(): 清空缓存。

org.springframework.cache.CacheManager:这个接口定义了如何获取Cache实例。它有一个重要的方法:

  • Cache getCache(String name): 根据缓存的名称获取Cache实例。

Spring通过这些接口与各种缓存实现(如EhCache,Redis,Hazelcast等)进行交互。要使用Spring的缓存功能,只需配置一个实现了CacheManager接口的Bean,然后在需要使用缓存的地方使用@Cacheable,@CacheEvict和@CachePut等注解即可。

开启注解

Spring 为缓存功能提供了注解功能,但是你必须启动注解:

(1) 在 xml 中声明

使用cache:annotation-driven/<cache:annotation-driven cache-manager=“cacheManager”/>

(2) 使用标记注解

通过对一个类进行注解修饰的方式在这个类中使用缓存注解。

范例如下:

@Configuration
@EnableCaching
public class AppConfig {
}

缓存注解使用

Spring 对缓存的支持类似于对事务的支持。首先使用注解标记方法,相当于定义了切点,然后使用 Aop 技术在这个方法的调用前、调用后获取方法的入参和返回值,进而实现了缓存的逻辑。

@Cacheable

表明所修饰的方法是可以缓存的:当第一次调用这个方法时,它的结果会被缓存下来,在缓存的有效时间内,以后访问这个方法都直接返回缓存结果,不再执行方法中的代码段。

这个注解可以用condition属性来设置条件,如果不满足条件,就不使用缓存能力,直接执行方法。可以使用key属性来指定 key 的生成规则。

范例如下:

@Service  
public class ExampleService {

@Cacheable("examples")
public String getExample(String key) {
// 模拟一个耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Example for " + key;
}
}

@CachePut

与@Cacheable不同,@CachePut不仅会缓存方法的结果,还会执行方法的代码段。当一个方法被标记为 @CachePut,Spring 会在该方法执行后更新缓存。它支持的属性和用法都与@Cacheable一致。

范例如下:

 @Service  
public class ExampleService {

@CachePut("examples")
public void updateExample(String key, String value) {
// 更新数据的操作
// ...
}
}

@CacheEvict

与@Cacheable功能相反,@CacheEvict表明所修饰的方法是用来删除失效或无用的缓存数据。当一个方法被标记为 @CacheEvict,Spring 会在该方法执行后从缓存中移除相关的数据。

范例如下:

@Service  
public class ExampleService {

@CacheEvict(value = "examples", key = "#id")
public void evictExample(String id) {
// 从缓存中移除数据的操作
// ...
}
}

@Cacheable、@CacheEvict和@CachePut使用方法的集中展示示例:

@Service
public class UserService {
// @Cacheable可以设置多个缓存,形式如:@Cacheable({"books", "isbns"})
@Cacheable(value={"users"}, key="#user.id")
public User findUser(User user) {
return findUserInDB(user.getId());
}

@Cacheable(value = "users", condition = "#user.getId() <= 2")
public User findUserInLimit(User user) {
return findUserInDB(user.getId());
}

@CachePut(value = "users", key = "#user.getId()")
public void updateUser(User user) {
updateUserInDB(user);
}

@CacheEvict(value = "users")
public void removeUser(User user) {
removeUserInDB(user.getId());
}

@CacheEvict(value = "users", allEntries = true)
public void clear() {
removeAllInDB();
}
}

@Caching

如果需要使用同一个缓存注解(@Cacheable、@CacheEvict或@CachePut)多次修饰一个方法,就需要用到@Caching。

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

@CacheConfig

与前面的缓存注解不同,这是一个类级别的注解。如果类的所有操作都是缓存操作,你可以使用@CacheConfig来指定类,省去一些配置。

@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}

缓存存储

Spring 允许通过配置方式接入多种不同的缓存存储。用户可以根据实际需要选择。

不同的缓存存储,具有不同的性能和特性。

使用 ConcurrentHashMap 作为缓存

示例配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

<description>使用 ConcurrentHashMap 作为 Spring 缓存</description>
<context:component-scan base-package="io.github.dunwu.spring.cache"/>

<bean id="simpleCacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="users"/>
</set>
</property>
</bean>

<cache:annotation-driven cache-manager="simpleCacheManager"/>
</beans>

使用 Ehcache 作为缓存

示例配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

<description>使用 EhCache 作为 Spring 缓存</description>

<!--配置参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-store-configuration-->

<context:component-scan base-package="io.github.dunwu.spring.cache"/>

<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache/ehcache.xml"/>
</bean>

<bean id="ehcacheCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>

<cache:annotation-driven cache-manager="ehcacheCacheManager"/>
</beans>

ehcache.xml 中的配置内容完全符合 Ehcache 的官方配置标准。

使用 Caffeine 作为缓存

示例配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

<description>使用 Caffeine 作为 Spring 缓存</description>

<!--配置参考:https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-store-configuration-->

<context:component-scan base-package="io.github.dunwu.spring.cache"/>

<bean id="caffeineCacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager"/>

<cache:annotation-driven cache-manager="caffeineCacheManager"/>
</beans>

参考资料

https://docs.spring.io/

文章目录
  1. 1. 缓存接口
  2. 2. 开启注解
    1. 2.0.1. (1) 在 xml 中声明
    2. 2.0.2. (2) 使用标记注解
  • 3. 缓存注解使用
    1. 3.0.1. @Cacheable
    2. 3.0.2. @CachePut
    3. 3.0.3. @CacheEvict
    4. 3.0.4. @Caching
    5. 3.0.5. @CacheConfig
  • 4. 缓存存储
    1. 4.0.1. 使用 ConcurrentHashMap 作为缓存
    2. 4.0.2. 使用 Ehcache 作为缓存
    3. 4.0.3. 使用 Caffeine 作为缓存