這裏新增長一個例子:java
`spring
package com.atguigu.cache.service; import com.atguigu.cache.bean.Employee; import com.atguigu.cache.mapper.EmployeeMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.*; import org.springframework.stereotype.Service; @CacheConfig(cacheNames = "emp") [@Service](https://my.oschina.net/service) public class EmployeeService { @Autowired EmployeeMapper employeeMapper; /** * 將方法的運行結果進行緩存,之後在要相同的數據,直接從緩存中獲取,不用調用方法 * * CacheManager管理多個Cache組件的,對緩存的真正CRUD操做在Cache組件中,每個緩存 * 組件有本身惟一一個名字 * * 幾個屬性: * cacheName/value:指定緩存組件的名字;將方法的返回結果放在哪一個緩存中,是數組的方式,能夠指定多個緩存; * key:緩存數據使用的key,能夠用它來指定,默認是使用方法參數的值 1-方法的返回值 * 編寫SqEL; #id,參數id的值 #a0 #p0 #root.args[0] * keyGenerator:key的生成器;能夠本身指定key的生成器的組件 * key/keyGenerator:二選一使用 * cacheManager:緩存管理器;或者cacheResolver指定獲取解析器 * condition:指定符合條件的狀況下才緩存; * condition="#id>0" * condition="#a0>1"l;第一個參數的值>1 的時候才進行緩存 * (a0等於arg[0]) * unless:否認緩存;當unless指定的條件爲true,方法的返回值就不會被緩存;能夠 * 獲取到結果進行判斷unless="#a0==2":若是第一參數的值是2,結果不緩存 * sync:是否使用異步模式:異步模式不支持unless * * 原理: * 1.緩存的自動配置類;CacheAutoConfiguration * 2.緩存的配置類 * org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration * org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration * org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration * org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration * org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration * org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration * org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration * org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration * org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默認】 * org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration * 3.哪一個配置類生效; SimpleCacheConfiguration * * 4.給容器中註冊了一個CacheManager、ConcurrentMapCacheManager * 5.能夠獲取和建立ConcurrentMapCache類型的緩存組件;他的做用將數據保存在ConcurrentMap中; * * 運行流程: * @Cacheable: * 1.方法運行以前,先去查詢Cache(緩存組件),按照cacheNames指定的名字獲取; * (CacheManager先獲取相應的緩存),第一次獲取緩存若是沒有Cache組件會自動建立, * 2.去Cache中查找緩存的內容,使用一個key,默認就是方法的參數; * key是按照某種策略生成的;默認是使用keyGenerator生成的,默認使用 * SimpleKeyGenerator生成key的默認策略; * 若是沒有參數;key=new SimpleKey(); * 若是有一個參數,key=參數的值 * 若是有多個參數:key=new SimpleKey(params); * 3.沒有查到緩存就調用目標方法; * 4.將目標方法的緩存結果,放進緩存中 * * @Cacheable標註的方法執行以前先來檢查緩存中有沒有這個數據,默認按照參數的值做爲key去查詢緩存, * 若是沒有就運行方法並將結果放入緩存,之後再來調用就能夠直接使用緩存中的數據 * * 核心: * 1)、使用CacheManager【ConcurrentMapCacheManager】按照名字獲得Cache【ConcurrentMapCache】組件 * 2)、key使用keyGenerator生成的,默認是SimpleKeyGenerator * @param id * @return */ @Cacheable(value = {"emp"}/*,keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#a0==2"*/) public Employee getEmp(Integer id){ System.out.println("查詢"+id+"號員工"); Employee emp=employeeMapper.getEmpById(id); return emp; } /** * @CachePut:即調用方法,又更新緩存數據:同步更新緩存 注意key要相同 * 修改了數據庫的某個數據,同時更新緩存; * 運行時機: * 一、先調用目標方法 * 二、將目標方法的結果緩存起來 * * 測試步驟: * 一、查詢1號員工;查到的結果會放在緩存中 * key:1 value: lastName:張三 * 二、之後查詢仍是以前的結果 * 三、更新1號員工;【LastName:zhangsan:gender:0】 * 將方法的返回值也放進緩存了; * key: 傳入的employee對象 值:返回employee對象; * 四、查詢1號員工? * 應該是更新後的員工; * key = "#employee.id":使用傳入的參數的員工的id; * key = "#result.id";使用返回後的id * @Cacheable的key是不能用#result: * 緣由:由於@Cacheable運行時機有兩個,一個是在運行方法以前 * 一個是在運行方法以後,咱們要在方法一開始就獲得key,Put * 是先執行方法的,而able是先執行註解的 * 爲何是沒更新前的?【1號員工更新了,只是用的key不同】 */ @CachePut(/*value = "emp",*/key = "#result.id") public Employee updateEmp(Employee employee){ System.out.println("updateEmp:"+employee); employeeMapper.updateEmp(employee); return employee; } /** * @CacheEvict:緩存清除 * key:指定要清除的數據 * allEntries=true:指定清除這個緩存中全部數據 * beforeInvocation=false:緩存的清除是否在方法以前執行 * 默認表明緩存清除操做是在方法執行以後執行;若是出現異常緩存就 * 不會清除 * * beforeInvocation = true: * 表明清除緩存操做是在方法運行以前執行,不管是否出現異常,緩存都清除 */ @CacheEvict(/*value = "emp",*/beforeInvocation = true/*,key = "#id"*/) public void deleteEmp(Integer id){ System.out.println("deleteEmp:"+id); /*employeeMapper.deleteEmpById(id);*/ } /** * @Caching 定義複雜的緩存規則 * 這裏意味着當你再用id或email調用時,則不須要再執行SQL語句 * @param lastName * @return */ @Caching( cacheable = { @Cacheable(/*value = "emp",*/key = "#lastName") }, put = { @CachePut(/*value = "emp",*/key = "#result.id"), @CachePut(/*value = "emp",*/key = "#result.email")//有@CachePut出現,下面的方法就必定會執行 } ) //你依照id,郵箱,名字均可以得到該value public Employee getEmpByLastName(String lastName){ System.out.println("複雜緩存"); return employeeMapper.getEmpByLastName(lastName); } }
` 這裏主要說了SpringCache註解的功能,而且更加詳細數據庫
可是我在另外一項目中使用這些註解卻出現了一些意外主要是由於key本來是String類型,可是我沒有將負值key爲id的屬性轉成String,這裏則說明有些須要轉型,有些則不須要:數組
`緩存
package cn.enilu.subor.service.system.impl; import cn.enilu.subor.bean.entity.system.Video; import cn.enilu.subor.dao.system.VideoRepository; import cn.enilu.subor.service.system.VideoService; import cn.enilu.subor.utils.factory.MutiStrFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @CacheConfig(cacheNames = "video") @Service public class VideoServiceImpl implements VideoService { @Autowired private VideoRepository videoRepository; @Override public Page<Video> findAll(Pageable var1) { return videoRepository.findAll(var1); } @Override //@Cacheable(value = {"video"}) public List<Video> findAll() { return videoRepository.findAll(); } @Override @CachePut(key = "#video.id.toString()") public Video save(Video video) { return videoRepository.save(video); } @Override @CacheEvict(key = "#id.toString()") public void delete(Integer id) { System.out.println("dddddddddddddddddddd"+id); videoRepository.delete(id); } @CachePut(key = "#video.id.toString()") public void update(Video video){ System.out.println("uuuuuuu"); System.out.println("38218401779274902148901249012"+video); Integer videoId=video.getId(); //String title=video.getTitle(); String video_introduce=video.getVideoIntroduce(); String video_type=video.getVideoType(); Integer video_class=video.getVideoClass(); //String video_url=video.getVideoUrl(); //String img_title=video.getImgTitle(); // String img_url=video.getImgUrl(); videoRepository.updateById2(video_class,video_introduce,video_type,videoId); } }
`app
這裏在附上註解的源碼,key的類型爲Stringless
`dom
package org.springframework.cache.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface CachePut { @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; String key() default ""; String keyGenerator() default ""; String cacheManager() default ""; String cacheResolver() default ""; String condition() default ""; String unless() default ""; }
`異步