緩存註解Cache

SpringBoot緩存註解 @CacheConfig、@Cacheable、@CachePut、@CacheEvict、@Caching

將方法的運行結果進行緩存;以後再要有相同的數據,直接從緩存中獲取,不用調用方法;
CacheManager管理多個Cache組件,對緩存的真正CRUD操作在Cache組件中,每一個緩存組件有自己唯一一個名字;
在這裏插入圖片描述

@Cacheable

@Cacheable可以標記在一個方法上,也可以標記在一個類上。當標記在一個方法上時表示該方法是支持緩存的,當標記在一個類上時則表示該類所有的方法都是支持緩存的。對於一個支持緩存的方法,Spring會在其被調用後將其返回值緩存起來,以保證下次利用同樣的參數來執行該方法時可以直接從緩存中獲取結果,而不需要再次執行該方法。Spring在緩存方法的返回值時是以鍵值對進行緩存的,值就是方法的返回結果,至於鍵的話,Spring又支持兩種策略,默認策略和自定義策略,這個稍後會進行說明。需要注意的是當一個支持緩存的方法在對象內部被調用時是不會觸發緩存功能的。
Cache中value屬性是必須指定的,其表示當前方法的返回值是回被緩存在哪個Cache上的。cacheNames/value;指定緩存的名字
將方法的返回值放到哪個緩存中 其盛放的只一個數組的方式存放的
@Cacheable註解在調用方法之前 查看是否有緩存

cacheable上的value註解

   @Cacheable("emp")
   public Employee get(Integer id) {
   	  System.out.println("查詢"+id+"號員工");
      return null;
   }
   @Cacheable({"emp1", "emp2"})
   public Employee  find(Integer id) {
      return null;
   }
	@Cacheable(cacheNames = {"emp"})
	public Employee getEmp(Integer id){
		System.out.println("查詢"+id+"號員工");
		Employee emp=employeeMapper.getEmpById(id);
		return emp;
	}

key屬性的應用

key屬性是用來指定Spring緩存方法的返回結果時對應的key的。該屬性支持SpringEL表達式。當我們沒有指定該屬性時,Spring將使用默認策略生成key。
key:緩存數據使用的key;可以用他來指定。默認是使用方法參數的值 1-方法的返回值
編寫SpEl表達式:#root.methodName當前被調用的方法名
#root.method.name當前被調用的方法
#root.target當前被調用的目標對象
#root.args[0]當前被調用的方法的參數列表
#root.targetClass當前被調用的目標對象類

//這裏的#id表示入參時的id   
@Cacheable(cacheNames = {"emp"},key="#id")
    public Employee getEmp(Integer id){
        System.out.println("查詢"+id+"號員工");
        Employee emp=employeeMapper.getEmpById(id);
        return emp;
    }
//key中的#id和#root.args[0]一樣都是將id作爲key
	@Cacheable(cacheNames = "emp",key="#root.args[0]")
		public Employee getEmp(Integer id){
		System.out.println("查詢"+id+"號員工");
		Employee emp=employeeMapper.getEmpById(id);
		return emp;
	}
@Cacheable(value="users", key="#p0")
   public User find(Integer id) {
      return null;
   }
//如果是對象入參時可以"."出來
@Cacheable(value="users", key="#user.id")
   public User find(User user) {
      return null;
   }
@Cacheable(value="users", key="#p0.id")
   public User find(User user) {
      return null;
   }
//可以自己指定key與不指定是一樣的效果默認使用入參的id  如果入參是一個對象或map可以.出來
@Cacheable(cacheNames = {"emp"},key = "#root.methodName+'['+#id+']'")
public Employee getEmp(Integer id){
	System.out.println("查詢"+id+"號員工");
	Employee emp=employeeMapper.getEmpById(id);
	return emp;
}

當我們要使用root對象的屬性作爲key時我們也可以將“#root”省略,因爲Spring默認使用的就是root對象的屬性。

@Cacheable(value={"users", "xxx"}, key="caches[1].name")
   public User find(User user) {
      return null;
   }

在這裏插入圖片描述

condition:指定合適條件的情況下才緩存;當參數的id大於0時纔將方法的運行結果進行緩存

//condition="#id>0"  id大於0時纔將方法運行的結果進行緩存
@Cacheable(cacheNames = "emp",condition="#id>0")
public Employee getEmp(Integer id){
System.out.println("查詢"+id+"號員工");
Employee emp=employeeMapper.getEmpById(id);
return emp;
}
//condition滿足條件時開啓緩存  不滿足條件不進行緩存
@Cacheable(cacheNames = "emp",condition="#id>0")
	public Employee getEmp(Integer id){
	System.out.println("查詢"+id+"號員工");
	Employee emp=employeeMapper.getEmpById(id);
	return emp;
}

//可以寫很多
如:condition="#id>0 and #root.methodName eq 'aa'"

unless:否定緩存;當unless指定的條件爲true,方法的返回值就不會被緩存;可以獲取到的結果進行判斷

//unless指定的條件爲true時不會進行緩存
@Cacheable(cacheNames = "emp",condition="#id>0",unless="#result == null")
public Employee getEmp(Integer id){
	System.out.println("查詢"+id+"號員工");
	Employee emp=employeeMapper.getEmpById(id);
	return emp;
}

@CachePut

@CachePut即調用方法,又跟新緩存數據
修改了數據庫的某個數據,同時更新緩存
cacheput是方法運行完後纔在緩存中放東西

在支持Spring Cache的環境下,對於使用@Cacheable標註的方法,Spring在每次執行前都會檢查Cache中是否存在相同key的緩存元素,如果存在就不再執行該方法,而是直接從緩存中獲取結果進行返回,否則纔會執行並將返回結果存入指定的緩存中。@CachePut也可以聲明一個方法支持緩存功能。與@Cacheable不同的是使用@CachePut標註的方法在執行前不會去檢查緩存中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。
@CachePut也可以標註在類上和方法上。使用@CachePut時我們可以指定的屬性跟@Cacheable是一樣的。

//key = "#employee.id"(使用傳入的參數的id) 與key = "#result.id"相同(使用返回後的id)
@CachePut(value = "emp",key = "#result.id")
public Employee updateEmp(Employee employee){
   System.out.println("updateEmp"+employee);
   employeeMapper.updateEmp(employee);
   return employee;
}

cacheable與cacheput註解的不同是:cacheable註解是在調用之前查看緩存中是否有key緩存的數據
cacheput先調用目標方法,將目標方法的結果緩存起來 指定id後才能跟新緩存中的東西,沒指定只是會修改數據庫中的值而不是修改緩存中的
cacheable中的key定義不能使用#result. 因爲是方法之前進行的緩存檢查操作

@CacheEvict

@CacheEvict;緩存清除
刪除某個數據後將其從緩存中清除出去
key:指定要清除的數據
@CacheEvict(value = “emp”,key = “#id”,allEntries = true)
allEntries = true 是否刪除緩存中的所有數據
beforeInvocation=false:緩存的清除是否在方法之前執行
默認代表是在方法執行之後執行;如果出現異常緩存就不會清除
@CacheEvict(value = “emp”,beforeInvocation = true,key = “#id”)
代表清除緩存的操作是在方法運行之前執行無論方法是否出現異常緩存都清除

@CacheEvict(value = "emp",beforeInvocation = true,key = "#id")
public void deleteEmp(Integer id){
   employeeMapper.deleteEmpById(id);
}

@Caching

@Caching註解可以讓我們在一個方法或者類上同時指定多個Spring Cache相關的註解。其擁有三個屬性:cacheable、put和evict,分別用於指定@Cacheable、@CachePut和@CacheEvict。
@Caching 可以進行多緩存 定義複雜的緩存結果
如果標註CachePut則cacheable相當於失效,有cacheable方法一定執行

@Caching(
   cacheable = {
     @Cacheable(value = "emp",key = "#lastName")
   },
   put = {
     @CachePut(value = "emp",key = "#result.id"),
     @CachePut(value = "emp",key = "#result.email")
   }
)
public Employee getEmpByLastName(String lastName){
	return employeeMapper.getEmpByLastName(lastName);
}

自定義註解

也可以自定義緩存可以的配置類
方法一

@Configuration
public class MyCacheConfig {

    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(){
        return new KeyGenerator(){

            @Override
            public Object generate(Object target, Method method,Object... params){
                return method.getName()+"["+ Arrays.asList(params).toString()+"]";
            }
        };
    }
}

使用自定義的配置類進行緩存key

@Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator")
public Employee getEmp(Integer id){
	System.out.println("查詢"+id+"號員工");
	Employee emp=employeeMapper.getEmpById(id);
	return emp;
}

方法二

//自定義緩存註解類
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(value="users")
public @interface MyCacheable {
 
}

那麼在我們需要緩存的方法上使用@MyCacheable進行標註也可以達到同樣的效果。

   @MyCacheable
   public User findById(Integer id) {
      System.out.println("find user by id: " + id);
      User user = new User();
      user.setId(id);
      user.setName("Name" + id);
      return user;
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章