前言:
本文檔將講解一下,如何借助Spring Module項目,實現配置聲明性緩存功能。
聲明式緩存配置有效地將緩存功能從應用程序的核心需求中分離出來,解決了上文提及的眾多問題,還帶來了以下優點:
- 更明晰的責任分離。系統中的模塊僅負責其核心需求,不再負責緩存功能。這將帶來更出色的可追溯性。
- 更高的模塊化程度。將緩存功能從核心模塊中分離出來減少了重復代碼(支持“一次且僅一次”原則),并有助于避免代碼混亂。
- 設計決策的后期綁定。使用聲明式緩存,開發人員可將與緩存實現和調優有關的決策制訂延后。開發人員可將精力集中在應用程序的當前核心需求上。聲明式配置支持 YAGNI(“you aren't gonna need it”的縮寫,意為“您將不會需要它)原則,僅在開發人員確實需要的時候才允許他們為應用程序添加緩存,而且不需要進行系統級的更改。
說明:
本檔的配置經過本人測試,都能正確運行。
運行環境: Jdk5.0, Spring-2.5, Spring-modules-0.9, ehcache-1.6.0-beta4.jar
首先創建一個StudentService服務類,本文將對其所有的以get* 方式命令的方法,進行緩存處理。當調用set* 命令時,需要其刪除緩存
以更做數據的更新。
源代碼如下:
1 public class StudentService {
2
3 private String name = "matthew";
4
5 public String getName() {
6 return name;
7 }
8
9 public String getName(String salution) {
10 return salution + " " + name;
11 }
12
13 public void setName(String name) {
14 this.name = name;
15 }
16
17 public void changeNameAndNotTellCache(String name) {
18 this.name = name;
19 }
20 }
接下來,就是編寫Spring配置文件 context.xml,以實現根據上面的要求,進行聲明性緩存功能的配置
Spring的配置內容如下:(已加上注釋)
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
5
6 <!-- Using a EHCache cache manager -->
7 <bean id="cacheManager"
8 class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
9 <!--<property name="cacheManagerName" value="mainCache"/>-->
10 <property name="configLocation" value="classpath:ehcache.xml" />
11 </bean>
12
13 <!-- 使用Spring Modules對 EhCache的封裝 -->
14 <bean id="cacheProviderFacade" class="org.springmodules.cache.provider.ehcache.EhCacheFacade">
15 <property name="cacheManager" ref="cacheManager" />
16 </bean>
17
18 <!-- 配置 方法 攔截器 -->
19 <!-- 緩存攔截器 -->
20 <bean id="cachingInterceptor"
21 class="org.springmodules.cache.interceptor.caching.MethodMapCachingInterceptor">
22 <property name="cacheProviderFacade" ref="cacheProviderFacade" />
23 <property name="cachingModels"> <!-- 進行cache緩存 -->
24 <props> <!-- 所有StudentService對象中,以get開頭的方法都將進行緩存 -->
25 <prop key="StudentService.get*">cacheName=testCache</prop>
26 </props>
27 </property>
28 </bean>
29
30 <!-- 緩存刷新攔截器 -->
31 <bean id="flushingInterceptor"
32 class="org.springmodules.cache.interceptor.flush.MethodMapFlushingInterceptor">
33 <property name="cacheProviderFacade" ref="cacheProviderFacade" />
34 <property name="flushingModels"><!-- 進行cache刷新(清除) -->
35 <props>
36 <prop key="StudentService.set*">cacheNames=testCache</prop>
37 </props>
38 </property>
39 </bean>
40
41 <!-- 配置 基于BeanName規則的動態代理封裝 -->
42 <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
43 <property name="beanNames">
44 <list>
45 <value>studentService</value>
46 </list>
47 </property>
48 <property name="interceptorNames">
49 <list>
50 <value>cachingInterceptor</value>
51 <value>flushingInterceptor</value>
52 </list>
53 </property>
54 </bean>
55
56 <bean id="studentService" class="StudentService"></bean>
57 </beans>
接下來,為能讓EhCache能正常工作,還得編寫EhCache配置文件 ehcache.xml, 內容如下:
1 <ehcache>
2 <diskStore path="java.io.tmpdir" />
3 <defaultCache maxElementsInMemory="10000" eternal="false"
4 timeToIdleSeconds="2" timeToLiveSeconds="5" overflowToDisk="true"
5 maxElementsOnDisk="10000000" diskPersistent="false"
6 diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />
7 <cache name="testCache" maxElementsInMemory="10000"
8 maxElementsOnDisk="1000" eternal="false" overflowToDisk="false"
9 diskSpoolBufferSizeMB="20" timeToIdleSeconds="60" timeToLiveSeconds="3600"
10 memoryStoreEvictionPolicy="LFU" />
11 </ehcache>
下面將要測試配置是否能正確工作,編寫一個測試類 Test.java內容如下:
1 public class Test {
2
3 /**
4 * @param args
5 */
6 public static void main(String[] args) {
7 AbstractApplicationContext context;
8 context = new ClassPathXmlApplicationContext("classpath*:context.xml");
9 context.start();
10
11 StudentService ss = (StudentService) context.getBean("studentService");
12
13 String name;
14 System.out.println("第一次訪問,沒有緩存");
15 name = ss.getName();
16 System.out.println(name);
17 name = ss.getName("Mr");
18 System.out.println(name);
19
20 //use change not changed value
21 System.out.println("第二次訪問,使用緩存");
22 ss.changeNameAndNotTellCache("Michael");
23 name = ss.getName();
24 System.out.println(name);
25
26 name = ss.getName("Mr");
27 System.out.println(name);
28
29 //update cache
30 System.out.println("清除緩存后,再次訪問 ");
31 ss.setName("Michael");
32 name = ss.getName();
33 System.out.println(name);
34
35 name = ss.getName("Mr");
36 System.out.println(name);
37
38 context.close();
39 }
40
41 }
運行后的輸出結果:
第一次訪問,沒有緩存
matthew
Mr matthew
第二次訪問,使用緩存
matthew
Mr matthew
清除緩存后,再次訪問
Michael
Mr Michael
從輸出的結果上來看,緩存的功能已經正確啟效。
本文只是一個簡單的示例,希望對大家有借鑒作用。
更多的資料,詳見官方文檔
https://springmodules.dev.java.net/.
Good Luck!
Yours Matthew!