一、基本介绍
在Java中,注解本身不缓存数据,但有一些框架利用注解来简化缓存的配置和使用。比如:Spring Framework,Spring的缓存注解包括:
@Cacheable:用于标记方法,以便Spring在调用该方法时将结果缓存起来。
@CachePut:用于更新缓存中的数据,而不是仅从缓存中读取数据。
@CacheEvict:用于从缓存中移除数据。
@Caching:组合使用多个缓存注解。
@Cacheable 注解是 Spring 框架提供的一种简便方式,用于实现方法级别的缓存。@Cacheable 可以显著提升应用性能,通过避免重复计算或重复访问数据源来减少开销。@Cacheable 注解用于标记那些需要缓存其返回结果的方法。当方法被调用时,Spring 会检查缓存中是否已有该方法参数对应的结果。如果有,Spring 会直接从缓存中返回结果;如果没有,Spring 会调用方法执行,并将返回结果放入缓存中。
示例代码
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable("test")
public String getItemById(String id) {
// 模拟一个耗时的操作
simulateSlowService();
return "test data for " + id;
}
private void simulateSlowService() {
try {
Thread.sleep(3000L); // 3秒
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
在这个例子中,getItemById 方法的结果会被缓存到名为 test 的缓存中。第一次调用此方法时,Spring 会执行方法并将结果存入缓存。随后相同参数的调用会直接从缓存中返回结果,而不会再次调用方法。
二、环境配置
1、maven依赖
在使用Spring的@Cacheable注解时,需要引入Spring的缓存支持依赖。以下是常用的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
除了spring-boot-starter-cache依赖外,还需要根据具体的缓存实现引入对应的依赖。
a、使用EhCache作为缓存实现
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
--配置缓存管理器
spring
cache
type: ehcache
b、使用Caffeine 作为缓存实现
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.0</version>
</dependency>
c、使用Redis 作为缓存实现
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring
redis
host: 127.0.0.1
port: 6379
password:
引入以上依赖后,可以在Spring应用中配置Redis连接信息,并使用@Cacheable注解来实现方法级别的缓存功能。在配置文件中配置Redis的连接信息,然后在需要缓存的方法上添加@Cacheable注解,并指定缓存的名称,即可实现方法的结果缓存到Redis中。
三、配置缓存管理器
在使用 @Cacheable 之前,你需要配置缓存管理器。Spring 支持多种缓存提供者,例如内存缓存(如 ConcurrentMapCacheManager)、Ehcache、Redis 等。
ConcurrentMapCacheManager缓存管理器
示例代码
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("test");
}
}
在这个配置类中,@EnableCaching 注解启用缓存支持,ConcurrentMapCacheManager 是一种简单的内存缓存管理器,test是缓存的名称。
缓存名称:@Cacheable 注解中的 value 属性指定缓存的名称。这个名称需要与缓存管理器中配置的缓存名称一致。
缓存键:默认情况下,Spring 使用方法参数作为缓存的键。如果你需要自定义缓存键,可以使用 key 属性。
示例代码:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "items", key = "#id + #name")
public String getItem(String id, String name) {
// 模拟一个耗时的操作
simulateSlowService();
return "Item data for " + id + " and " + name;
}
}
条件缓存
使用 condition 属性可以根据条件决定是否缓存结果。
示例代码:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "items", condition = "#id.length() > 3")
public String getItem(String id) {
// 模拟一个耗时的操作
simulateSlowService();
return "Item data for " + id;
}
}
缓存空值
使用 unless 属性可以指定缓存条件,默认情况下,Spring 不缓存方法返回 null 的结果。如果你需要缓存 null,可以通过 unless 属性来配置。
示例代码:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable(value = "items", unless = "#result == null")
public String getItem(String id) {
// 模拟一个耗时的操作
simulateSlowService();
return null; // 示例中返回 null
}
}
清除缓存
如果你需要在缓存中的数据被更新或删除时清除缓存,可以使用 @CacheEvict 注解。
示例代码:
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@CacheEvict(value = "items", allEntries = true)
public void clearCache() {
// 清除缓存中的所有条目
}
}
在这个例子中,clearCache 方法会清除 items 缓存中的所有条目。
总结
1、使用 @Cacheable 注解:在方法上添加 @Cacheable 注解,使得方法返回值被缓存。
2、配置缓存管理器:配置缓存管理器以便 Spring 可以使用缓存。
3、自定义缓存键:通过 key 属性自定义缓存键。
4、条件缓存:使用 condition 和 unless 属性来控制缓存行为。
5、清除缓存:使用 @CacheEvict 注解来清除缓存条目。