@Cacheable 注解是 Spring Cache 抽象的一部分,用于声明式地管理缓存。@Cacheable 注解本身并不直接指定缓存的存储位置,而是依赖于配置的缓存管理器(CacheManager)来决定缓存数据的存储位置。
常见的缓存存储方式:
1、内存缓存:
Simple Cache Manager:默认情况下,Spring 使用 ConcurrentMapCacheManager,它将缓存数据存储在内存中的 ConcurrentHashMap 中。
Caffeine:Caffeine 是一个高性能的内存缓存库,常用于本地缓存。Spring Cache 可以集成 Caffeine 作为缓存管理器。
2、分布式缓存:
Redis:Redis 是一个高性能的键值存储系统,支持网络、持久化、多语言 API 等特性。Spring Cache 可以通过 RedisCacheManager 集成 Redis。
Ehcache:Ehcache 是一个广受欢迎的分布式缓存解决方案,支持本地缓存和分布式缓存。Spring Cache 可以通过 EhCacheCacheManager 集成 Ehcache。
Hazelcast:Hazelcast 是一个开源的内存数据网格,支持分布式缓存。Spring Cache 可以通过 HazelcastCacheManager 集成 Hazelcast。
下面举例在 Spring Boot 应用程序中结合 Redis 实现缓存。我们将使用 @Cacheable 注解来缓存方法的结果,并使用 RedisCacheManager 作为缓存管理器。
1. 添加依赖 首先,在 pom.xml 中添加必要的依赖:
xml
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Spring Boot Starter Cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Lombok (可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
2. 配置 Redis
在 application.properties 文件中配置 Redis 连接信息:
yaml
spring.redis.host=localhost
spring.redis.port=6379
3. 配置缓存管理器
创建一个配置类来配置 RedisCacheManager:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
@Configuration
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 设置缓存过期时间为1小时
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
}
}
ps: 补充一下,使用ConcurrentMapCacheManager 默认的缓存方式:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
@Configuration
public class CacheConfig {
//spring 默认的缓存配置
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("personal_Cache");
}
}
4. 创建缓存接口和实现
创建一个简单的接口和实现类,用于演示缓存功能:
java
// 缓存接口
public interface CacheService {
String getAttribute(String key);
}
// 缓存实现类
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class CacheServiceImpl implements CacheService {
@Override
@Cacheable(value = "attributes", key = "#key")
public String getAttribute(String key) {
// 模拟耗时的数据库查询或其他操作
try {
Thread.sleep(2000); // 模拟延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Attribute value for " + key;
}
//清除缓存
@Override
@CacheEvict(value = "attributes", key = "#key")
public void evictAttribute(String key) {
.....
}
}
5. 创建控制器
创建一个控制器来测试缓存功能:
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CacheController {
@Autowired
private CacheService cacheService;
//模拟使用缓存
@GetMapping("/getAttribute")
public String getAttribute(@RequestParam String key) {
return cacheService.getAttribute(key);
}
//模拟清除缓存
@GetMapping("/evictAttribute")
public String evictAttribute(@RequestParam String key) {
return cacheService.evictAttribute(key);
}
}
6. 启动类
创建一个启动类来启动 Spring Boot 应用程序:
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
总结
通过上述步骤,我们成功地在 Spring Boot 应用程序中集成了 Redis 作为缓存存储,并使用 @Cacheable 注解实现了方法级别的缓存。这样可以显著提高应用程序的性能,特别是在处理频繁且耗时的数据查询时。