轻松使用Spring的缓存功能
这是一个使用Spring(Spring Boot)的缓存功能来缓存方法调用结果的示例。
确认动作版本
-
- Spring Boot 2.7.5
- Spring Framework 5.3.23
启用缓存功能
当使用 @EnableCaching 注解后,Spring Boot 的自动配置功能会使得可以使用 Spring 的缓存功能。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching // ★★★アノテーションを追加
public class SpringCacheDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCacheDemoApplication.class, args);
}
}
指定缓存目标方法
給希望將結果快取的方法加上@Cacheable標記。在以下示例中,我們將緩存名稱設定為「rates」。
package com.example.demo;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.UUID;
@Component
public class RateRepository {
@Cacheable("rates") // ★★★ キャッシュしたいメソッドにアノテーションを追加
public Rate getRate(String unitId, String groupId, String type, String baseDate) {
Rate rate = new Rate();
rate.setId(UUID.randomUUID().toString());
rate.setRate(BigDecimal.valueOf(new SecureRandom().nextLong()));
return rate;
}
}
试着动一下
当运行以下JUnit时,可以发现在以相同参数调用方法的情况下,将返回缓存的实例。
@SpringBootTest
class SpringCacheDemoApplicationTests {
@Autowired
RateRepository rateRepository;
@Test
void contextLoads() {
Rate rate1 = rateRepository.getRate("U001", "G001", "Credit", "20221114");
Rate rate2 = rateRepository.getRate("U001", "G001", "Credit", "20221114");
// ★★★ 同じインスタンスが返却される
Assertions.assertThat(rate2.getId()).isEqualTo(rate1.getId());
Assertions.assertThat(rate2.getRate()).isEqualTo(rate1.getRate());
Assertions.assertThat(rate2).isSameAs(rate1);
}
}
在测试类中删除缓存
为了确保测试不会影响其他测试,我们最好在每次测试之前清除已缓存的数据。因此,在测试类中注入CacheManager来清除缓存。
@SpringBootTest
class SpringCacheDemoApplicationTests {
@Autowired
RateRepository rateRepository;
@Autowired
CacheManager cacheManager;
// ★★★ テスト実施前後にキャッシュをクリアする
@BeforeEach
@AfterEach
void clearCache() {
cacheManager.getCacheNames().stream()
.map(cacheManager::getCache)
.filter(Objects::nonNull)
.forEach(Cache::clear);
}
@Test
void contextLoads() {
Rate rate1 = rateRepository.getRate("U001", "G001", "Credit", "20221114");
Rate rate2 = rateRepository.getRate("U001", "G001", "Credit", "20221114");
Assertions.assertThat(rate2.getId()).isEqualTo(rate1.getId());
Assertions.assertThat(rate2.getRate()).isEqualTo(rate1.getRate());
Assertions.assertThat(rate2).isSameAs(rate1);
// ★★★ 明示的にキャッシュを削除してみる
clearCache();
// ★★★ キャッシュ削除後に同じパラメータでメソッドを呼び出しみる
Rate rate3 = rateRepository.getRate("U001", "G001", "Credit", "20221114");
// ★★★ Cacheクリア後は別のインスタンスが返却される
Assertions.assertThat(rate3.getId()).isNotEqualTo(rate1.getId());
Assertions.assertThat(rate3.getRate()).isNotEqualTo(rate1.getRate());
Assertions.assertThat(rate3).isNotSameAs(rate1);
}
}
请参考以下页面
-
- https://docs.spring.io/spring-boot/docs/2.7.5/reference/htmlsingle/#io.caching
- https://docs.spring.io/spring-framework/docs/5.3.23/reference/html/integration.html#cache