在springcache之前
在沒(méi)有使springcache之前我們使用緩存的方式是這樣的:
Map<StoreKey, List<SpecialHall>> keyListHashMap = Maps.newHashMap();
DateTime dt = new DateTime().withHourOfDay(2).plusDays(1);
DateTime now = DateTime.now();
int toTwo = (int) (dt.getMillis() - now.getMillis()) / 1000;
List<SpecialHall> resList = Lists.newArrayList();
for (Integer cinemaId : cinemaIds) {
StoreKey storeKey = new StoreKey(CacheConstants.GDATA_STRING, String.format(CacheConstants.GATEWAY_SPECIALS_BY_CINEMAID, cinemaId));
keyListHashMap.put(storeKey, resList);
returnTocMap.put(cinemaId, transToTSpecialHallToApp(resList));
}
redisStoreClient.multiSet(keyListHashMap, toTwo);
這段代碼我剛開(kāi)始看的時(shí)候也覺(jué)得沒(méi)問(wèn)題,還覺(jué)得寫的挺好的(因?yàn)槭俏覍懙耐敌Γ任铱吹搅藄pringcache之后我覺(jué)得這段代碼就不是那么的優(yōu)雅了粘秆,總體來(lái)說(shuō)就是代碼的處理邏輯和緩存耦合在一起,降低了代碼的可讀性,不利于后期人員的維護(hù);還有就是緩存切換的話成本很大昔善,需要改動(dòng)的地方比較多,風(fēng)險(xiǎn)成本比較高畔乙。
在springcache之后
springcache是什么君仆?
首先,要明白springcache是一種解決緩存的方案牲距,而不是一種具體的緩存方式(類似的Redis返咱,memcache,ehcache等等)牍鞠。
springcache的相關(guān)配置
pom配置:
這里需要注意spring應(yīng)該是3.1+
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
springcache相關(guān)xml配置
<!-- ehcache -->
<cache:annotation-driven cache-manager="ehcacheManager"/>
<!-- 聲明cacheManager -->
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcacheManagerFactory" />
</bean>
<!-- cacheManager工廠類咖摹,指定ehcache.xml的位置 -->
<bean id="ehcacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
還需要配置具體的緩存:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false">
<diskStore path="/Users/yuxi/work/myoschina/tmpdir"/>
<!--
name:緩存名稱。
maxElementsInMemory:緩存最大個(gè)數(shù)难述。
eternal:對(duì)象是否永久有效萤晴,一但設(shè)置了,timeout將不起作用龄广。
timeToIdleSeconds:設(shè)置對(duì)象在失效前的允許閑置時(shí)間(單位:秒)硫眯。
僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用蕴侧,可選屬性择同,默認(rèn)值是0,也就是可閑置時(shí)間無(wú)窮大净宵。
timeToLiveSeconds:設(shè)置對(duì)象在失效前允許存活時(shí)間(單位:秒)敲才。最大時(shí)間介于創(chuàng)建時(shí)間和失效時(shí)間之間。
僅當(dāng)eternal=false對(duì)象不是永久有效時(shí)使用择葡,默認(rèn)是0.紧武,也就是對(duì)象存活時(shí)間無(wú)窮大。
overflowToDisk:當(dāng)內(nèi)存中對(duì)象數(shù)量達(dá)到maxElementsInMemory時(shí)敏储,Ehcache將會(huì)對(duì)象寫到磁盤中阻星。
diskSpoolBufferSizeMB:這個(gè)參數(shù)設(shè)置DiskStore(磁盤緩存)的緩存區(qū)大小。默認(rèn)是30MB。每個(gè)Cache都應(yīng)該有自己的一個(gè)緩沖區(qū)妥箕。
maxElementsOnDisk:硬盤最大緩存?zhèn)€數(shù)滥酥。
diskPersistent:是否緩存虛擬機(jī)重啟期數(shù)據(jù) Whether the disk store persists between restarts
of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盤失效線程運(yùn)行時(shí)間間隔,默認(rèn)是120秒畦幢。
memoryStoreEvictionPolicy:當(dāng)達(dá)到maxElementsInMemory限制時(shí)坎吻,Ehcache將會(huì)根據(jù)指定的策略去清理內(nèi)存。
默認(rèn)策略是LRU(最近最少使用)宇葱。你可以設(shè)置為FIFO(先進(jìn)先出)或是LFU(較少使用)瘦真。
clearOnFlush:內(nèi)存數(shù)量最大時(shí)是否清除。
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="60"
timeToLiveSeconds="60"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="dbCache" maxElementsInMemory="10000" eternal="false"
timeToLiveSeconds="1800" overflowToDisk="false" diskPersistent="true"/>
</ehcache>
springcache的相關(guān)代碼實(shí)現(xiàn)
package com.yuxi.cache;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* Created by yuxi on 2017/9/28.
*/
@Service("cacheService")
public class CacheService {
@Cacheable(value = "dbCache", key = "'info_' + #id")
public Info getInfo(Integer id) {
System.out.println("from cache");
return getDb(id);
}
private Info getDb(Integer id) {
System.out.println("from db" + id);
return new Info(id);
}
@CachePut(value = "dbCache", key = "'info_' + #id")
public Info getInfo2(Integer id) {
System.out.println("from cache put");
return getDb(id);
}
@CacheEvict(value = "dbCache", key = "'info_' + #id")
public boolean delete(Integer id) {
System.out.println("delete");
return true;
}
}
相關(guān)測(cè)試類
package com.yuxi.main;
import com.yuxi.cache.CacheService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by yuxi on 2017/8/5.
*/
public class KnightMain {
public static void main(String[] args) {
// spring 應(yīng)用上下文
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("knight.xml");
CacheService cacheService = (CacheService) applicationContext.getBean("cacheService");
cacheService.getInfo(1);
cacheService.getInfo(1);
cacheService.getInfo(1);
cacheService.getInfo(1);
cacheService.getInfo(1);
cacheService.getInfo2(1);
cacheService.getInfo2(1);
cacheService.getInfo2(1);
cacheService.delete(1);
}
}
相關(guān)的測(cè)試結(jié)果為:
from cache
from db1
from cache put
from db1
from cache put
from db1
from cache put
from db1
delete
springcache的相關(guān)注解說(shuō)明:
三圖勝過(guò)萬(wàn)言黍瞧,圖片來(lái)自郭老師的wiki诸尽,不要問(wèn)我郭老師是誰(shuí)?他是一個(gè)傳說(shuō)雷逆。
郭老師的wiki
郭老師的wiki
郭老師的wiki
相關(guān)代碼可以參考:springcache