Spring 快取註解@Cacheable的用法

OkidoGreen發表於2020-04-05

https://blog.csdn.net/qq_17555933/article/details/51320800

  在Spring中通過獲取MemCachedClient來實現與memcached伺服器進行資料讀取的方式。不過,在實際開發中,我們往往是通過Spring的@Cacheable來實現資料的快取的,所以,本文給大家詳細介紹一下@Cacheable的用法。首先,在使用@Cacheable之前,我們要做好準備工作。

第一步:要匯入相應的jar包。
   

<classpathentry kind="lib" path="lib/spring-core-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/spring-cache-1.0.10.jar"/>
    <classpathentry kind="lib" path="lib/spring-context-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/spring-beans-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/commons-logging-1.2.jar"/>
    <classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
    <classpathentry kind="lib" path="lib/spring-expression-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/java_memcached-release_2.0.1.jar"/>
    <classpathentry kind="lib" path="lib/spring-aop-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/spring-aspects-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/spring-context-support-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/spring-tx-4.1.4.RELEASE.jar"/>
    <classpathentry kind="lib" path="lib/aopalliance-1.0.jar"/>
    <classpathentry kind="lib" path="lib/ognl-3.0.6.jar"/>
    <classpathentry kind="lib" path="lib/trafficCounter-1.0.2.jar"/>
    <classpathentry kind="lib" path="lib/aspectjweaver-1.8.4.jar"/>
    <classpathentry kind="lib" path="lib/javassist-3.11.0.GA.jar"/>

第二步:xml檔案中增加名稱空間。

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/cache
    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">


之後新增如下宣告:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/cache
    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
    <!-- 啟用快取註解功能,這個是必須的,否則註解不會生效,另外,該註解一定要宣告在spring主配置檔案中才會生效 --> 
    <cache:annotation-driven cache-manager="cacheManager" />
    
    <!-- cacheManager工廠類,指定ehcache.xml的位置 -->   
    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
        <property name="configLocation"  value="classpath:cache/ehcache.xml"/>  
    </bean>
    
    <!-- 宣告cacheManager -->  
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="cacheManagerFactory"/>
    </bean>
</beans>


第二步: ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
    updateCheck="false" dynamicConfig="false" monitoring="autodetect">  
    <diskStore path="java.io.tmpdir" />
    <!--
        diskStore path:用來配置磁碟快取使用的物理路徑
        name:    快取名稱,cache的唯一標識(ehcache會把這個cache放到HashMap裡)
        eternal="false"   元素是否永恆,如果是就永不過期(必須設定)
        maxElementsOnDisk====磁碟快取中最多可以存放的元素數量,0表示無窮大 
        maxElementsInMemory="1000" 記憶體快取中最多可以存放的元素數量(必須設定)
        timeToIdleSeconds="0"   導致元素過期的訪問間隔(秒為單位). 0表示可以永遠空閒,預設為0
        timeToLiveSeconds="600" 元素在快取裡存在的時間(秒為單位). 0 表示永遠存在不過期
        overflowToDisk="false"  當快取達到maxElementsInMemory值是,是否允許溢位到磁碟(必須設定)
        diskPersistent="false"  磁碟快取在VM重新啟動時是否保持(預設為false)
        diskExpiryThreadIntervalSeconds="100" 磁碟失效執行緒執行時間間隔,預設是120秒
        memoryStoreEvictionPolicy="LFU" 記憶體儲存與釋放策略.當達到maxElementsInMemory時
               共有三種策略,分別為LRU(最近最少使用)、LFU(最常用的)、FIFO(先進先出)預設使用"最近使用"策略
    -->
    <defaultCache  
        eternal="false"
        maxElementsInMemory="3000"  
        timeToIdleSeconds="3600"  
        timeToLiveSeconds="0"  
        overflowToDisk="true"  
        diskPersistent="false"  
        diskExpiryThreadIntervalSeconds="100"  
        memoryStoreEvictionPolicy="LRU"/>
 
    <cache name="propConfigCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
    <cache name="workTimeCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
    
    <cache name="threeInOneCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
    
    <cache name="transferCache"  
        eternal="false"
        maxElementsInMemory="1000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
    <cache name="threeInOneFavCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
    <cache name="reserveTimeCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
    <cache name="mqServerNameCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
    <cache name="schWorkTimeCache"  
        eternal="false"
        maxElementsInMemory="3000"  
        overflowToDisk="true"
        timeToIdleSeconds="0"  
        timeToLiveSeconds="1440" 
        memoryStoreEvictionPolicy="LFU"/>
        
</ehcache>


@Cacheable 支援如下幾個引數:

value:快取位置名稱,不能為空,如果使用EHCache,就是ehcache.xml中宣告的cache的name

key:快取的key,預設為空,既表示使用方法的引數型別及引數值作為key,支援SpEL

condition:觸發條件,只有滿足條件的情況才會加入快取,預設為空,既表示全部都加入快取,支援SpEL

//將快取儲存進andCache,並使用引數中的userId加上一個字串(這裡使用方法名稱)作為快取的key   
@Cacheable(value="andCache",key="#userId + 'findById'")  
public SystemUser findById(String userId) {  
    SystemUser user = (SystemUser) dao.findById(SystemUser.class, userId);        
    return user ;         
}  

//將快取儲存進andCache,並當引數userId的長度小於32時才儲存進快取,預設使用引數值及型別作為快取的key  
@Cacheable(value="andCache",condition="#userId.length < 32")  
public boolean isReserved(String userId) {  
    System.out.println("hello andCache"+userId);  
    return false;  
} 


@CacheEvict 支援如下幾個引數:

value:快取位置名稱,不能為空,同上

key:快取的key,預設為空,同上

condition:觸發條件,只有滿足條件的情況才會清除快取,預設為空,支援SpEL

allEntries:true表示清除value中的全部快取,預設為false

  //清除掉指定key的快取  
    @CacheEvict(value="andCache",key="#user.userId + 'findById'")  
    public void modifyUserRole(SystemUser user) {  
             System.out.println("hello andCache delete"+user.getUserId());  
    }  
      
    //清除掉全部快取  
    @CacheEvict(value="andCache",allEntries=true)  
    public final void setReservedUsers(String[] reservedUsers) {  
        System.out.println("hello andCache deleteall");  
    }


一般來說,我們的更新操作只需要重新整理快取中某一個值,所以定義快取的key值的方式就很重要,最好是能夠唯一,因為這樣可以準確的清除掉特定的快取,而不會影響到其它快取值 ,

比如我這裡針對使用者的操作,使用(userId+方法名稱)的方式設定key值 ,當然,你也可以找到更適合自己的方式去設定。

EhCache 是一個純Java的程式內快取框架,具有快速、精幹等特點,是Hibernate中預設的CacheProvider。

Ehcache是一種廣泛使用的開源Java分散式快取。主要面向通用快取,Java EE和輕量級容器。它具有記憶體和磁碟儲存,快取載入器,快取擴充套件,快取異常處理程式,一個gzip快取servlet過濾器,支援REST和SOAP api等特點。
Ehcache最初是由Greg Luck於2003年開始開發。2009年,該專案被Terracotta購買。軟體仍然是開源,但一些新的主要功能(例如,快速可重啟性之間的一致性的)只能在商業產品中使用,例如Enterprise EHCache and BigMemory。,維基媒體Foundationannounced目前使用的就是Ehcache技術。

主要的特性有:
1. 快速
2. 簡單
3. 多種快取策略
4. 快取資料有兩級:記憶體和磁碟,因此無需擔心容量問題
5. 快取資料會在虛擬機器重啟的過程中寫入磁碟
6. 可以通過RMI、可插入API等方式進行分散式快取
7. 具有快取和快取管理器的偵聽介面
8. 支援多快取管理器例項,以及一個例項的多個快取區域
9. 提供Hibernate的快取實現

相關文章