以Spring整合EhCache為例從根本上了解Spring緩存這件事(轉)
前兩節“Spring緩存抽象”和“基於註解驅動的緩存”是為了更加清晰的了解Spring緩存機制,整合任何一個緩存實現或者叫緩存供應商都應該了解並清楚前兩節,如果只是為了快速的應用EhCache到Spring項目中,請直接前往第三節“Spring整合EhCache緩存”。
一、 Spring緩存抽象
1. 註意和核心思想
Spring自身並沒有實現緩存解決方案,但是對緩存管理功能提供了聲明式的支持,能夠與多種流行的緩存實現進行集成。
Spring Cache是作用在方法上的(不能理解為只註解在方法上),其核心思想是:當我們在調用一個緩存方法時會把該方法參數和返回結果作為一個鍵值存放在緩存中,等到下次利用同樣的參數調用該方法時將不再執行該方法,而是直接從緩存中獲取結果進行返回。所以在使用Spring Cache的時候我們要保證我們的緩存的方法對於相同的方法參數要有相同的返回結果。
2. Spring對Cache的支持有兩種方式
- 基於註解驅動的緩存
- 基於XML配置聲明的緩存
下來我們介紹基於註解驅動的緩存
二、 基於註解驅動的緩存
在往bean上添加緩存註解之前,必須要啟動Spring對註解驅動緩存的支持
1. 啟用Spring對註解驅動緩存的支持
啟用Spring對註解驅動緩存的支持,也是有兩種方式的:
- Java配置(這個方法可以比較清晰的了解緩存管理器是如何聲明的)
- XML配置(這個方法比較方便簡單,這裏的XML配置不能跟上面的“基於XML配置聲明的緩存”搞混,兩者不是同一層概念)
下面用一個簡單的例子來說明這兩種方法的區別,這跟Spring整合EhCache沒什麽關系,但是可以讓大家搞懂緩存管理器
程序清單1: Java配置啟用註解驅動的緩存
[java] view plain copy print?
- package com.snieri.authentication.ehcache;
- import org.springframework.cache.CacheManager;
- import org.springframework.cache.annotation.EnableCaching;
- import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
- import org.springframework.context.annotation.Configuration;
- @Configuration
- @EnableCaching//啟用緩存
- public class CachingConfig {
- /**
- * 聲明緩存管理器
- */
- public CacheManager cacheManager() {
- return new ConcurrentMapCacheManager();
- }
- }
程序清單2:XML配置啟用註解驅動緩存
[html] view plain copy print?- <cache:annotation-driven/>
- n id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager"></bean>
這兩種方式,Java配置方式是通過使用@EnableCaching啟用註解驅動的緩存,XML配置方式是通過使用<cache:annotation-driven/>啟用註解驅動的緩存。本質上來講,這兩種工作方式是相同的,它們都會創建一個切面(AOP)並出發Spring緩存註解的切點(pointcut)。
在這兩個程序清單中,不僅僅啟用了註解驅動的緩存,還聲明了一個緩存管理器(cache manager)的bean。緩存管理器是Spring抽象的核心,它能夠與多個流行的緩存實現進行集成。這裏又提到這句話,請大家切記。
上面的例子聲明了一個ConcurrentMapCacheManager,這個簡單的緩存管理器使用java.util.concurrent.ConcurrentHashMap作為其緩存存儲。這個緩存非常簡單,對於開發、測試或其他基礎的應用來講,是一個不錯的選擇。但是它的緩存存儲是基於內存的,所以它的聲明周期是與應用關聯的,對於生產級別的大型企業級應用程序,這個緩存並不理想。
幸好,Spring有多個緩存管理器方案可供選擇,請看下節。
2. 緩存管理器(這裏的概念搞清楚很重要)
Spring內置很多緩存管理器(從Spring3到Spring4好像有7個吧,記不太清了,有興趣的可以查查)
SimpleCacheManager
NoOpCacheManager
ConcurrentMapCacheManager(這個緩存管理器就是上面的例子介紹的)
CompositeCacheManager
EhCacheCacheManager(看到這裏終於見到標題主人翁了)
RedisCacheManager(來自Spring Date Redis項目)
GemfireCacheManager(來自Spring Date GemFire項目)
可以看到,在為Spring的緩存抽象選擇緩存管理器時,我們有很多可選方案。具體選擇哪一個要取決於想要使用的底層緩存供應商。每一個方案都可以為應用提供不同風格的緩存,其中有一些會比其他的更加適用於生產環境。盡管所做出的選擇會影響到數據如何緩存,但是Spring聲明緩存的方式並沒有什麽差別。也就是說,無論你用什麽緩存管理器,Spring聲明緩存的方式是不變的,註解驅動緩存(java配置啟動、XML配置啟動)和XML配置緩存兩種方式。
三、 Spring整合EhCache緩存
在往bean上添加緩存註解之前,必須要啟動Spring對註解驅動緩存的支持,所以說有兩個步驟:
啟用Spring對註解驅動緩存的支持
聲明某些方法或者整個類使用緩存,這一步包含編寫ehcache.xml文件(後面會有詳細介紹)
1. 啟用Spring對註解驅動緩存的支持
這裏依然介紹的是基於註解驅動,上面已經講了,有兩個啟動方式:Java配置的方式和XML配置的方式(兩種方式本質是一樣的)。XML是我們常見的啟動方式。
程序清單3:以Java配置的方式設置EhCacheManager
[java] view plain copy print?
- package com.snieri.authentication.ehcache;
- import org.springframework.cache.annotation.EnableCaching;
- import org.springframework.cache.ehcache.EhCacheCacheManager;
- import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.io.ClassPathResource;
- import net.sf.ehcache.CacheManager;
- @Configuration
- @EnableCaching//啟用緩存
- public class CachingConfig {
- /**
- * @param cacheManager 是 net.sf.ehcache.CacheManager的一個實例
- * 配置EhCacheCacheManager緩存管理器
- */
- @Bean
- public EhCacheCacheManager cacheManager(CacheManager cacheManager) {
- return new EhCacheCacheManager(cacheManager);
- }
- @Bean
- public EhCacheManagerFactoryBean ehcache() {
- EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
- ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("**/**/ehcache.xml"));
- return ehCacheManagerFactoryBean;
- }
- }
程序清單4:以XML配置的方式設置EhCacheManager
[html] view plain copy print?- <!-- 啟用緩存 -->
- <cache:annotation-driven cache-manager ="cacheManager" />
- <!--聲明一個緩存管理器(EhCacheCacheManager) 這裏的實現代碼是通過傳入EhCache的CacheManager實例實現的 -->
- <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
- <!--這裏並不是EhCacheManagerFactoryBean的實例,而是EhCache中CacheManager的一個實例 -->
- <!--因為Spring和EhCache都定義了CacheManager類型 -->
- <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation" value="classpath:/ehcache.xml" />
- <property name="shared" value="true"/>
- </bean>
在程序清單3中,cacheManager()方法創建了一個EhCacheCacheManager實例,這是通過傳入EhCache的cacheManager實例實現的。這裏比較詭異,讓人感到迷惑,而且在導包的時候往往會容易導錯,這是因為Spring和EhCache都定義了CacheManager類型。需要明確的是,EhCache的CacheManager要被註入到Spring的EhCacheCacheManager之中。
可以從import的包中也可以查看到這些信息(這也算是馬後炮了,但是有助於我們理解)。下面這段比較重要,認真思考。
*我們需要使用EhCache的CacheManager來進行註入,所以必須聲明一個CacheManager bean。為了對其進行簡化,Spring提供了EhCacheManagerFactoryBean來生成EhCache的CacheManager。方法ehcache()會創建並返回一個EhCacheManagerFactoryBean實例。因為它是一個工廠bean(也就是說,它實現了Spring的FactoryBean接口),所以註冊在Spring應用上下文的並不是EhCacheManagerFactoryBean的實例,而是EhCache的CacheManager實例,因此適合註入到EhCacheCacheManager之中。
2. 聲明某些方法或整個類哪個使用緩存並且編寫ehcache.xml文件
下面兩個內容可以在我轉載的另一個博文《Spring使用Cache》中查看,比較清晰,結合起來的話應該會對spring緩存有所了解。
1) 為方法或類添加註解以支持緩存
2) ehcache.xml配置
而以下的這兩節我會在不久進行整理,註意查看我的博文。
四、 Spring整合Redis緩存
五、 Spring整合使用多個緩存管理器
以Spring整合EhCache為例從根本上了解Spring緩存這件事(轉)