Spring Boot中的EnableCaching簡述
spring boot中自帶有資料快取機制,主要通過其org.springframework.cache包下的各種類來實作,
EnableCaching
@EnableCaching是啟用快取的注解,標注在任何一個可自動注入的類上即可開啟,
Cacheable
@Cacheable是一個標注與類與方法上的注解,用于表示此類或此方法需要使用快取機制,當類與方法上都有時,采用 就近原則,
在@Cacheable注解中,有一些常用引數可以進行配置:
value與cacheNames- 表示系結的快取名稱,這里的快取指的是單個的快取存盤器,并不是最終的鍵值對快取物件,key- 表示快取物件的 key,這個才是最終的快取鍵值對的 key,這里的引數需要使用 SpEL運算式,keyGenerator- 表示用于生成此方法 快取key的類,與key引數只能選擇一個添加,否則會拋出IllegalStateException例外,cacheManager- 指定快取管理器,這個后面再細說,condition- 快取的條件,支持SpEL,當快取條件滿足時,才會進入快取取值模式,unless- 排除的條件,支持SpEL,當排除的條件滿足時,會直接呼叫方法取值,sync- 異步快取模式,是否采用異步的方式,在方法取值時異步快取,默認false,在快取完成后才回傳值,
一般情況下,可以這樣使用:
@RestController
@RequestMapping("cache")
@Cacheable(value = "https://www.cnblogs.com/Verlif/p/cache", sync = true)
public class CacheController {
@Cacheable(value = "https://www.cnblogs.com/Verlif/p/hello", sync = true, keyGenerator = "myKeyGenerator")
@GetMapping("hello")
public String hello(String name) {
System.out.println("name - " + name);
return "hello " + name;
}
@GetMapping("hello2")
public String hello2(@RequestParam(defaultValue = "https://www.cnblogs.com/Verlif/p/1") Integer size, @RequestParam(defaultValue = "https://www.cnblogs.com/Verlif/p/world") String name) {
System.out.println("name - " + name);
return "hello " + name;
}
}
- 這里的
CacheController被標記上了@Cacheable(value = "https://www.cnblogs.com/Verlif/p/cache", sync = true),表示其下的方法默認使用名為cache的快取存取器,并采用異步的方式進行快取處理, hello方法上同樣添加了@Cacheable(value = "https://www.cnblogs.com/Verlif/p/hello", sync = true, keyGenerator = "myKeyGenerator"),使得hello方法使用了獨立的快取設定,并通過myKeyGenerator的策略來生成 快取key,
CachePut
將方法回傳值存入到快取中,一般情況下是用在更新操作中,并于Cacheable與CacheEvict配合使用,
CacheEvict
清除快取值,一般用在洗掉或更新操作中,并于Cacheable與CachePut配合使用,
并且在CacheEvict注解中,多了兩個引數:
allEntries- 清除當前value下的所有快取,beforeInvocation- 在方法執行前清除快取,
示例代碼示例如下:
@Cacheable(value = "https://www.cnblogs.com/Verlif/p/c", key = "123")
@GetMapping("hello")
public String hello(String name) {
System.out.println("name - " + name);
return "hello " + name;
}
@GetMapping("/put")
@CachePut(value = "https://www.cnblogs.com/Verlif/p/c", key = "123")
public String put() {
return "hello put";
}
@GetMapping("/evict")
@CacheEvict(value = "https://www.cnblogs.com/Verlif/p/c", key = "123")
public String evict() {
return "hello put";
}
上述代碼中,訪問hello介面時,會從c快取存取器中取出key為123的快取數值,沒有則會呼叫方法并進行快取,
訪問put介面時,會將c快取存取器中key為123的快取值改為hello put,沒有則進行快取,
訪問evict介面時,會將c快取存取器中key為123的快取值洗掉,此時訪問hello介面會重新呼叫方法并進行快取,
CacheConfig
@CacheConfig作為類上的注解,目的是為了統一配置其下的方法快取引數,并設定共享快取名,
cacheNames- 共享快取名陣列,設定后表示此類下的方法快取會依次從這些快取存取器中取值,如果有,則取用快取值;若沒有則呼叫方法取值,并快取值到設定的所有快取存取器中,
CacheManager
快取管理器介面,用來做快取管理的類,一般我們需要自定義快取策略時,就是從CacheManager來入手的,
直接上實體:
@Component
public class MyCacheManager implements CacheManager, InitializingBean {
private final Map<String, Cache> cacheMap;
public MyCacheManager() {
cacheMap = new HashMap<>();
}
@Override
public Cache getCache(String name) {
System.out.println("正在獲取快取 - " + name);
return cacheMap.computeIfAbsent(name, MyCache::new);
}
@Override
public Collection<String> getCacheNames() {
return cacheMap.keySet();
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("say something!");
}
}
CacheManager有兩個方法需要被實作:
getCache(String)- 獲取快取存取器,這里的name其實就對應了@Cacheable注解中的value與cacheName引數,getCacheNames- 獲取類中所有快取的名稱集合,這主要是為了Spring內部的統一管理需要,
因為 Spring采用了默認替補策略,所以我們使用@Component或是通過@Bean自動注入后,默認的快取管理器就會切換成我們自定義的,如果我們自定義了兩個的話,可以通過@Primary來設定默認管理器,
Cache
快取存取器,用來管理快取鍵值對的基本單元,
為了能對不同的快取采用不同的存取策略,我們可以定制不同的Cache,并通過自定義的CacheManager的getCache方法回傳對應的Cache,
舉個例子:
public final static class MyCache extends ConcurrentMapCache {
public MyCache(String name) {
super(name);
}
@Override
public <T> T get(Object key, Class<T> type) {
System.out.println("正在讀取 - " + key);
return super.get(key, type);
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
System.out.println("正在讀取 - " + key);
return super.get(key, valueLoader);
}
@Override
public ValueWrapper get(Object key) {
System.out.println("正在讀取 - " + key);
return super.get(key);
}
}
這里的MyCache集成了ConcurrentMapCache,并對每次快取值的獲取都進行了控制臺輸出,
KeyGenerator
快取key生成器,用于自定義規則快取key的生成,
其介面的方法只有一個:
public interface KeyGenerator {
Object generate(Object target, Method method, Object... params);
}
一目了然,通過呼叫的目標物件、目標方法與方法入參進行key的生成,這里不做過多贅述,
不過需要注意的是,由于不同類可能有同名同引數的方法,這里建議加上target.getClass().getName()來作為標記,避免出現不希望的快取映射,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/548447.html
標籤:Java
上一篇:作業系統面經-行程
