緩存 SpringModules Cache ( spring 和 ehcache的整合 ) spring提供緩存bean方案(轉載)

引自:<SPRING IN ACTION 2>

      Spring程序有一種更優雅的緩存解決方案。Spring Modules項目(http://springmodules.dev.java.net)通過切面提供了緩存,它把通知應用於Bean方法來透明地對其結果進行緩存,而不是明確地指定要被緩存的方法。

     Spring Modules對於緩存的支持涉及到一個代理,它攔截對Spring管理的Bean一個或多個的調用。當一個被代理的方法被調用時,Spring Modules Cache首先查閱一個緩存來判斷這個方法是否已經被使用同樣參數調用過,如果是,它會返回緩存裏的值,實際的方法並不會被調用;否則,實際方法會被調用,其返回值會被保存到緩存裏,以備方法下一次被調用時使用。

     雖然Spring Modules會提供一個代理來攔截方法並把結果保存到緩存,它並沒有提供一個實際的緩存解決方案,而是要依賴於第三方的緩存方案。可以使用的方案有多個,包括:

 EHCache

 GigaSpaces

 JBoss Cache

 JCS

 OpenSymphony 的 OSCache

 Tangosol 的 Coherence

 我們爲RoadRantz程序選擇EHCache,主要是因爲我以前使用它的經驗及能夠從www.ibibio.org的Maven倉庫輕易獲得。無論使用哪個緩存方案,對於Spring Modules Cache的配置基本上都是一樣的。

  首先要做的是新建一個Spring配置文件來聲明緩存。雖然可以把Spring Modules Cache配置放到RoadRantz程序加載的任意一個Spring上下文配置文件裏,但最好還是把他們分開,所以我們要創建roadrantz-cache.xml來保存緩存的配置。

  與Spring上下文配置文件一樣,randrantz-cache.xml也以<beans>元素爲根。但爲了利用Spring Modules 對EHCache的支持,我們要讓<beans>元素能夠識別ehcache命名空間:

  <?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:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:ehcache="http://www.springframework.org/schema/ehcache"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd 
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
            http://www.springframework.org/schema/ehcache  http://www.springframework.org/schema/cache/springmodules-ehcache.xsd">
 

  我們爲RoadRantz程序選擇的是EhCache,如果想使用其他緩存方案,需要把Spring Modules命名究竟和規劃聲明修改爲相應的內容。

  URI和規劃URI

 

 命名空間  命名空間URI  規劃URI
 ehcache  http://www.springframework.org/schema/ehcache  http://www.springframework.org/schema/cache/springmodules-ehcache.xsd
 gigaspaces  http://www.springframework.org/schema/gigaspaces  http://www.springframework.org/schema/springmodules-gigaspaces.xsd
 jboss  http://www.springframework.org/schema/jboss  http://www.springframework.org/schema/springmodules-jboss.xsd
 jcs  http://www.springframework.org/schema/jcs  http://www.springframework.org/schema/springmodules-jcs.xsd
 oscache  http://www.springframework.org/schema/oscache  http://www.springframework.org/schema/springmodules-oscache.xsd
 tangosol  http://www.springframework.org/schema/tangosol  http://www.springframework.org/schema/springmodules-tangosol.xsd

  無論選擇哪種緩存,都可以使用一些Spring配置元素在Sping裏對緩存進行配置。

Spring Modules的配置元素

 配置元素  用途
 <namespace:annotations>  以Java5註解來聲明被緩存的方式
 <namespace:commons-attributes>  以Jakarta通用屬性元素數據來聲明被緩存的方式
<namespace:config>  在Spring XML裏配置緩存方案 
<namespace:proxy>  在Spring XML裏聲明一個代理來聲明被緩存的方式 

 在使用EHCache作爲緩存方案時,需要告訴Spring到哪裏尋找EHCache配置文件,這正是<ehcache:config>元素的用途所在:

<ehcache:config configLocation="classpath:ehcache.xml">

在此對configLocation屬性的設置告訴Spring從程序類路徑的根位置加載EHCache的配置。

配置EHCache

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires.
                            i.e. The maximum amount of time between accesses before an element expires
                            Is only used if the element is not eternal.
                            Optional attribute. A value of 0 means that an Element can idle for infinity
        timeToLiveSeconds - Sets the time to live for an element before it expires.
                            i.e. The maximum time between creation time and when an element expires.
                            Is only used if the element is not eternal.
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
       
    <cache name="rantzCache"
        maxElementsInMemory="300"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="500"
        overflowToDisk="true"
        />
       
</ehcache>


<defulatCache>元素是必須的,描述了在沒有找到其他緩存情況下所使用的緩存。<cache>緩存定義了另一個緩存,可以在ehcache.xml裏出現0次或多次(每次針對定義的一個緩存)

EHCache的緩存配置屬性

 屬性  用於指定
 diskExpiryThreadIntervalSeconds  磁盤過期線程運行的頻率(以秒爲單位),也就是磁盤持久的緩存清理過期項目的頻率(默認是120秒)
 diskPersistent  磁盤緩存在VM重新啓動時是否保持(默認爲false)
 eternal 元素是否永恆。如果是永恆的,就永遠不會過期(必須設置) 
maxElementsInMemory  內存能夠被緩存的最大元素數量(必須設置) 
memoryStoreEvictionPolicy  當達到maxElementsInMemory時,如何強制進行驅逐。默認使用“最近使用(LRU)”策略,還可以使用“先入先出(FIFO)”和“較少使用(LFU)”策略。(默認是LRU) 
name  緩存的名稱(對於<cache>必須設置) 
 overflowToDisk 當內存緩存達到maxElementsInMemory時,是否可以溢出到磁盤(必須設置) 
timeToIdleSeconds  導致元素過期的訪問間接(以秒爲單位)。設置爲0標識元素可以永遠空閒(默認值爲0) 
timeToLiveSeconds  元素在緩存裏可以存在的時間(以秒爲單位)。設置爲0標識元素可以在緩存裏永遠存在而不過期(默認值是0) 

     對於RoadRantz程序,我們配置了一個默認緩存(這是EHCache要求的),還配置了一個名爲rantzCache的緩存作爲主緩存。兩個緩存都設置爲最多可以容納500個元素(不過期),訪問頻率最低的元素會被踢出,不允許磁盤溢出。

    在Spring程序上下文裏配置的EHCache之後,就可以聲明哪個Bean和方法應該對結果進行緩存。首先,我們來聲明一個代理來緩存RoadRantz DAO層裏方法的返回值。

 緩存的代理Bean

 我們已經知道HibernateRantDao裏的getRantsForDay()方法很適合進行緩存。再回到Spring上下文定義,我們要使用<ehcache:proxy>元素把一個代理包裹到HibernateRantDao,從而緩存從getRantsForDay()返回的全部內容:

<ehcache:proxy id="rantDao" refId="rantDaoTarget">

   <ehcache:caching methodName="getRantsForDay" cacheName="rantzCache"/>

</ehcache:proxy>

<ehcache:caching>元素聲明哪個方法要被攔截、其返回值要保存到哪個緩存。本例中,methodName被設置爲getRantsForDay(),要使用的緩存是rantzCache。

我們可以根據需要在<ehcache:proxy>裏聲明多個<ehcache:caching>來描述Bean方法的緩存。我們可以讓一個<ehcache:caching>用於所有被緩存的方法,也可以使用通配符爲一個<ehcache:caching>元素指定多個方法。比如下面的<ehcache:caching>元素會代理緩存全部名稱由get開頭的方法:

<ehcache:caching method="get*" cacheName="rantzCache"/>

 把數據放到緩存裏只完成了一半的工作。在經過一段時間之後,緩存裏一定會包含大量數據,其中很多沒有意義的數據。最後,這些數據應該被清理,數據緩存週期重新開始。

 刷新緩存

 <ehcache:caching>元素聲明的是要向緩存中添加數據的方法,而<ehcache:fluching>元素聲明瞭會清空緩存的方法。舉例來說,假設我們想在saveRant()方法被調用時清空rantzCache緩存,那麼就應該使用如下的<ehcache:flushing>元素:

<ehcache:flushing methodName="saveRant" cacheName="rantzCache"/>

在默認情況下,cacheName屬性裏指定的緩存會在methodName被調用之後清空,但利用when屬性可以指定清空的時機:

<ehcache:flushing methodName="saveRant" cacheName="rantzCache" when="before"/>

把when屬性設置爲before可以讓緩存在saveRant()被調用之前清空。

聲明一個被代替的內部Bean

 注意<ehcache:proxy>的id和refld屬性。由<ehcache:proxy>生成的代理的id是rantDao,然後這是HibernateRantDao Bean的id,因此,我們需要把這個真正的Bean重命名爲rantDaoTarget。

如果覺得id/refId組合有些奇怪,我們還可以把目標Bean聲明爲<ehcache:proxy>的內部Bean:

<ehcache:proxy id="rantDao">

<bean class="....">

<property name="sessionFactory" ref="sessionFactory"/>

</bean>

<ehcahe:caching methodName="getRantsForDay" cacheName="rantzCache"/>

</ehcache:proxy>

即使使用了內部Bean,我們仍然需要爲每個要代理的Bean聲明一個<ehcache:proxy>元素,爲方法聲明一個或多個<ehcache:caching>元素。

這個東東對我最大的吸引是,不再像以前,緊緊是hibernate對ehcache的支持了。也就是說,現在不論我用任何形式,我只是針對service或者Dao進行緩存就OK了。更易用

Demo1:

view plaincopy to clipboardprint?
<?xml version="1.0" encoding="UTF-8"?>     
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">     
<beans>     
    <!-- 引用ehCache的配置 -->     
    <bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">     
      <property name="configLocation">     
        <value>ehcache.xml</value>     
      </property>     
    </bean>     
         
    <!-- 定義ehCache的工廠,並設置所使用的Cache name -->     
    <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">     
      <property name="cacheManager">     
        <ref local="defaultCacheManager"/>     
      </property>     
      <property name="cacheName">     
          <value>DEFAULT_CACHE</value>     
      </property>     
    </bean>     
    
    <!-- find/create cache攔截器 -->     
    <bean id="methodCacheInterceptor" class="com.co.cache.ehcache.MethodCacheInterceptor">     
      <property name="cache">     
        <ref local="ehCache" />     
      </property>     
    </bean>     
    <!-- flush cache攔截器 -->     
    <bean id="methodCacheAfterAdvice" class="com.co.cache.ehcache.MethodCacheAfterAdvice">     
      <property name="cache">     
        <ref local="ehCache" />     
      </property>     
    </bean>     
         
    <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">     
      <property name="advice">     
        <ref local="methodCacheInterceptor"/>     
      </property>     
      <property name="patterns">     
        <list>     
            <value>.*find.*</value>     
            <value>.*get.*</value>     
        </list>     
      </property>     
    </bean>     
    <bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">     
      <property name="advice">     
        <ref local="methodCacheAfterAdvice"/>     
      </property>     
      <property name="patterns">     
        <list>     
          <value>.*create.*</value>     
          <value>.*update.*</value>     
          <value>.*delete.*</value>     
        </list>     
      </property>     
    </bean>     
</beans>   
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
<beans>  
    <!-- 引用ehCache的配置 -->  
    <bean id="defaultCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
      <property name="configLocation">  
        <value>ehcache.xml</value>  
      </property>  
    </bean>  
      
    <!-- 定義ehCache的工廠,並設置所使用的Cache name -->  
    <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
      <property name="cacheManager">  
        <ref local="defaultCacheManager"/>  
      </property>  
      <property name="cacheName">  
          <value>DEFAULT_CACHE</value>  
      </property>  
    </bean>  
 
    <!-- find/create cache攔截器 -->  
    <bean id="methodCacheInterceptor" class="com.co.cache.ehcache.MethodCacheInterceptor">  
      <property name="cache">  
        <ref local="ehCache" />  
      </property>  
    </bean>  
    <!-- flush cache攔截器 -->  
    <bean id="methodCacheAfterAdvice" class="com.co.cache.ehcache.MethodCacheAfterAdvice">  
      <property name="cache">  
        <ref local="ehCache" />  
      </property>  
    </bean>  
      
    <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
      <property name="advice">  
        <ref local="methodCacheInterceptor"/>  
      </property>  
      <property name="patterns">  
        <list>  
            <value>.*find.*</value>  
            <value>.*get.*</value>  
        </list>  
      </property>  
    </bean>  
    <bean id="methodCachePointCutAdvice" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
      <property name="advice">  
        <ref local="methodCacheAfterAdvice"/>  
      </property>  
      <property name="patterns">  
        <list>  
          <value>.*create.*</value>  
          <value>.*update.*</value>  
          <value>.*delete.*</value>  
        </list>  
      </property>  
    </bean>  
</beans> 
 

Demo2:

創建配置文件:

ehcache2.xml

view plaincopy to clipboardprint?
<ehcache> 
    <!-- Sets the path to the directory where cache .data files are created.  
         If the path is a Java System Property it is replaced by  
         its value in the running VM.  
         The following properties are translated:  
         user.home - User's home directory  
         user.dir - User's current working directory  
         java.io.tmpdir - Default temp file path --> 
    <diskStore path="java.io.tmpdir"/> 
 
    <!--Default Cache configuration. These will applied to caches programmatically created through  
        the CacheManager.  
        The following attributes are required for defaultCache:  
        maxInMemory       - Sets the maximum number of objects that will be created in memory  
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element  
                            is never expired.  
        timeToIdleSeconds - Sets the time to idle for an element before it expires.  
                            i.e. The maximum amount of time between accesses before an element expires  
                            Is only used if the element is not eternal.  
                            Optional attribute. A value of 0 means that an Element can idle for infinity  
        timeToLiveSeconds - Sets the time to live for an element before it expires.  
                            i.e. The maximum time between creation time and when an element expires.  
                            Is only used if the element is not eternal.  
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache  
                            has reached the maxInMemory limit.  
        --> 
    <defaultCache 
        maxElementsInMemory="10000" 
        eternal="false" 
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        overflowToDisk="true" 
        /> 
          
    <cache name="myCache1" 
        maxElementsInMemory="300" 
        eternal="false" 
        timeToIdleSeconds="500" 
        timeToLiveSeconds="500" 
        overflowToDisk="true" 
        /> 
          
</ehcache> 
<ehcache>
    <!-- Sets the path to the directory where cache .data files are created.
         If the path is a Java System Property it is replaced by
         its value in the running VM.
         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="java.io.tmpdir"/>

    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.
        The following attributes are required for defaultCache:
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires.
                            i.e. The maximum amount of time between accesses before an element expires
                            Is only used if the element is not eternal.
                            Optional attribute. A value of 0 means that an Element can idle for infinity
        timeToLiveSeconds - Sets the time to live for an element before it expires.
                            i.e. The maximum time between creation time and when an element expires.
                            Is only used if the element is not eternal.
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.
        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
       
    <cache name="myCache1"
        maxElementsInMemory="300"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="500"
        overflowToDisk="true"
        />
       
</ehcache>
 

 bean-jdbc.xml

view plaincopy to clipboardprint?
<?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:context="http://www.springframework.org/schema/context
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx
     xmlns:jee="http://www.springframework.org/schema/jee"   
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
           http://www.springframework.org/schema/context  
           http://www.springframework.org/schema/context/spring-context-2.5.xsd  
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd   
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd    
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 
    <context:property-placeholder location="classpath:jdbc_config.properties"/> 
    <!--   
        DriverManagerDataSource:在每個連接請求時新建一個連接。  
        SingleConnectionDataSource:在每個連接請求時都返回同一連接。  
     --> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName" value="${driverClassName}"/> 
        <property name="url" value="${url}"/> 
        <property name="username" value="${username}"/> 
        <property name="password" value="${password}"/> 
    </bean>   
</beans>   
  
<?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:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd 
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
 <context:property-placeholder location="classpath:jdbc_config.properties"/>
 <!--
  DriverManagerDataSource:在每個連接請求時新建一個連接。
  SingleConnectionDataSource:在每個連接請求時都返回同一連接。
  -->
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${driverClassName}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
 </bean>
</beans>
 

 beans-jdbc.xml

view plaincopy to clipboardprint?
<?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:context="http://www.springframework.org/schema/context
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx
     xmlns:jee="http://www.springframework.org/schema/jee"   
     xmlns:ehcache="http://www.springmodules.org/schema/ehcache
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    
           http://www.springframework.org/schema/context    
           http://www.springframework.org/schema/context/spring-context-2.5.xsd    
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd    
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd    
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd    
            http://www.springmodules.org/schema/ehcache  http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd"    
            default-autowire="byName"> 
    <import  resource="classpath:bean-jdbc.xml" /> 
    <!-- ehcache的各種配置策略 --> 
    <ehcache:config configLocation="classpath:ehcache2.xml"/> 
      
    <!--    
    <bean id="userManageService" class="cn.partner4java.ehcache.service.impl.UserManageServiceBean"></bean> 
    <ehcache:proxy id="userManageServicePro" refId="userManageService"> 
        <ehcache:caching methodName="query*" cacheName="myCache1"/> 
        <ehcache:flushing methodName="save" cacheNames="myCache1" when="before"/> 
        <ehcache:flushing methodName="delete*" cacheNames="myCache1"/> 
    </ehcache:proxy> 
    --> 
      
    <!-- 聲明緩存策略: cacheName屬性裏指定的緩存會在methodName被調用之後清空,但是利用when屬性可以指定清空的時機 --> 
    <ehcache:proxy id="userManageService"> 
        <bean class="cn.partner4java.ehcache.service.impl.UserManageServiceBean"></bean> 
        <ehcache:caching methodName="query*" cacheName="myCache1"/> 
        <ehcache:flushing methodName="save" cacheNames="myCache1" when="before"/> 
        <ehcache:flushing methodName="delete*" cacheNames="myCache1"/> 
    </ehcache:proxy> 
      
    <!-- 註解形式  
    <ehcache:annotations> 
        <ehcache:caching cacheName="myCache1" id="cacheModel"/> 
        <ehcache:flushing cacheNames="myCache1" id="flushModel" when="before"/> 
    </ehcache:annotations> 
    --> 
      
</beans>   
  
<?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:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:ehcache="http://www.springmodules.org/schema/ehcache"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-2.5.xsd 
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd 
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
            http://www.springmodules.org/schema/ehcache  http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd
            default-autowire="byName">
 <import resource="classpath:bean-jdbc.xml" />
 <!-- ehcache的各種配置策略 -->
 <ehcache:config configLocation="classpath:ehcache2.xml"/>
 
 <!-- 
 <bean id="userManageService" class="cn.partner4java.ehcache.service.impl.UserManageServiceBean"></bean>
 <ehcache:proxy id="userManageServicePro" refId="userManageService">
  <ehcache:caching methodName="query*" cacheName="myCache1"/>
  <ehcache:flushing methodName="save" cacheNames="myCache1" when="before"/>
  <ehcache:flushing methodName="delete*" cacheNames="myCache1"/>
 </ehcache:proxy>
 -->
 
 <!-- 聲明緩存策略: cacheName屬性裏指定的緩存會在methodName被調用之後清空,但是利用when屬性可以指定清空的時機 -->
 <ehcache:proxy id="userManageService">
  <bean class="cn.partner4java.ehcache.service.impl.UserManageServiceBean"></bean>
  <ehcache:caching methodName="query*" cacheName="myCache1"/>
  <ehcache:flushing methodName="save" cacheNames="myCache1" when="before"/>
  <ehcache:flushing methodName="delete*" cacheNames="myCache1"/>
 </ehcache:proxy>
 
 <!-- 註解形式
 <ehcache:annotations>
  <ehcache:caching cacheName="myCache1" id="cacheModel"/>
  <ehcache:flushing cacheNames="myCache1" id="flushModel" when="before"/>
 </ehcache:annotations>
 -->
 
</beans>
 

 一個用戶我後面單元測試的基礎類:

 view plaincopy to clipboardprint?
package cn.partner4java.utils;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
/** 
 * Junit 基礎功能類 
 *  
 * @author wangchanglong 
 *  
 */ 
public class SpringContextFactory {  
    private SpringContextFactory() {  
    }  
    private static ApplicationContext ac = new ClassPathXmlApplicationContext(  
            new String[] { "beans-jdbc.xml" });  
    private static SpringContextFactory springContextFactory;  
    public static SpringContextFactory getSpringContextFactory() {  
        if (springContextFactory == null) {  
            springContextFactory = new SpringContextFactory();  
        }  
        return springContextFactory;  
    }  
    public static ApplicationContext getApplicationContext() {  
        return getSpringContextFactory().ac;  
    }  
    /** 
     * 獲取spring代理對象 
     * @param beanName beanId or beanName 
     * @return 
     */ 
    public static Object getBean(String beanName) {  
        return getApplicationContext().getBean(beanName);  
    }  

package cn.partner4java.utils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * Junit 基礎功能類
 *
 * @author wangchanglong
 *
 */
public class SpringContextFactory {
 private SpringContextFactory() {
 }
 private static ApplicationContext ac = new ClassPathXmlApplicationContext(
   new String[] { "beans-jdbc.xml" });
 private static SpringContextFactory springContextFactory;
 public static SpringContextFactory getSpringContextFactory() {
  if (springContextFactory == null) {
   springContextFactory = new SpringContextFactory();
  }
  return springContextFactory;
 }
 public static ApplicationContext getApplicationContext() {
  return getSpringContextFactory().ac;
 }
 /**
  * 獲取spring代理對象
  * @param beanName beanId or beanName
  * @return
  */
 public static Object getBean(String beanName) {
  return getApplicationContext().getBean(beanName);
 }
}
 

我的實體bean:

view plaincopy to clipboardprint?
package cn.partner4java.ehcache.bean;  
import java.io.Serializable;  
/** 
 * 用戶測試表 
 * @author wangchanglong 
 * 
 */ 
public class User implements Serializable {  
    private int id;  
    private String userName;  
    private String password;  
    public User() {  
        super();  
    }  
      
    public User(String userName, String password) {  
        super();  
        this.userName = userName;  
        this.password = password;  
    }  
    public User(int id, String userName, String password) {  
        super();  
        this.id = id;  
        this.userName = userName;  
        this.password = password;  
    }  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public String getUserName() {  
        return userName;  
    }  
    public void setUserName(String userName) {  
        this.userName = userName;  
    }  
    public String getPassword() {  
        return password;  
    }  
    public void setPassword(String password) {  
        this.password = password;  
    }  
    @Override 
    public String toString() {  
        return "User [id=" + id + ", password=" + password + ", userName=" 
                + userName + "]";  
    }  
    @Override 
    public int hashCode() {  
        final int prime = 31;  
        int result = 1;  
        result = prime * result + id;  
        return result;  
    }  
    @Override 
    public boolean equals(Object obj) {  
        if (this == obj)  
            return true;  
        if (obj == null)  
            return false;  
        if (getClass() != obj.getClass())  
            return false;  
        User other = (User) obj;  
        if (id != other.id)  
            return false;  
        return true;  
    }  
      
      

package cn.partner4java.ehcache.bean;
import java.io.Serializable;
/**
 * 用戶測試表
 * @author wangchanglong
 *
 */
public class User implements Serializable {
 private int id;
 private String userName;
 private String password;
 public User() {
  super();
 }
 
 public User(String userName, String password) {
  super();
  this.userName = userName;
  this.password = password;
 }
 public User(int id, String userName, String password) {
  super();
  this.id = id;
  this.userName = userName;
  this.password = password;
 }
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 @Override
 public String toString() {
  return "User [id=" + id + ", password=" + password + ", userName="
    + userName + "]";
 }
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + id;
  return result;
 }
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  User other = (User) obj;
  if (id != other.id)
   return false;
  return true;
 }
 
 
}
 

接口:

view plaincopy to clipboardprint?
package cn.partner4java.ehcache.service;  
import java.util.List;  
import cn.partner4java.ehcache.bean.User;  
/** 
 *  
 * @author wangchanglong 
 * 
 */ 
public interface UserManageService {  
    public void save(User user);  
    public List<User> queryForList();  
    public void deleteById(int id);  

package cn.partner4java.ehcache.service;
import java.util.List;
import cn.partner4java.ehcache.bean.User;
/**
 *
 * @author wangchanglong
 *
 */
public interface UserManageService {
 public void save(User user);
 public List<User> queryForList();
 public void deleteById(int id);
}
 

實現類:

view plaincopy to clipboardprint?
package cn.partner4java.ehcache.service.impl;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;  
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;  
import org.springmodules.cache.annotations.CacheFlush;  
import org.springmodules.cache.annotations.Cacheable;  
import cn.partner4java.ehcache.bean.User;  
import cn.partner4java.ehcache.service.UserManageService;  
/** 
 *  
 * @author wangchanglong 
 * 
 */ 
public class UserManageServiceBean extends SimpleJdbcDaoSupport implements UserManageService {  
//  @CacheFlush(modelId="flushModel") //使用註解形式,需要打開配置文件的註解配置  
    public void deleteById(int id) {  
        Map parameters = new HashMap();  
        parameters.put("id", id);  
        this.getSimpleJdbcTemplate().update(USER_DELETE, parameters);  
    }  
      
    private static final String USER_DELETE = "delete from user where id = :id";  
//  @Cacheable(modelId="cacheModel")  
    public List<User> queryForList() {  
        List<User> users = this.getSimpleJdbcTemplate().query(USER_SELECT,   
                new ParameterizedRowMapper<User>() {  
                    public User mapRow(ResultSet rs, int rowNum) throws SQLException {  
                        User user = new User();  
                        user.setId(rs.getInt(1));  
                        user.setUserName(rs.getString(2));  
                        user.setPassword(rs.getString(3));  
                        return user;  
                    }  
        });  
        return users;  
    }  
      
    private static final String USER_SELECT = "select id,username,password from user ";  
    public void save(User user) {  
        Map parameters = new HashMap();  
        parameters.put("username", user.getUserName());  
        parameters.put("password", user.getPassword());  
        this.getSimpleJdbcTemplate().update(USER_INSERT, parameters);  
    }  
    private static final String USER_INSERT = "insert into user (username,password) values (:username, :password)";  
      

package cn.partner4java.ehcache.service.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
import org.springmodules.cache.annotations.CacheFlush;
import org.springmodules.cache.annotations.Cacheable;
import cn.partner4java.ehcache.bean.User;
import cn.partner4java.ehcache.service.UserManageService;
/**
 *
 * @author wangchanglong
 *
 */
public class UserManageServiceBean extends SimpleJdbcDaoSupport implements UserManageService {
// @CacheFlush(modelId="flushModel") //使用註解形式,需要打開配置文件的註解配置
 public void deleteById(int id) {
  Map parameters = new HashMap();
  parameters.put("id", id);
  this.getSimpleJdbcTemplate().update(USER_DELETE, parameters);
 }
 
 private static final String USER_DELETE = "delete from user where id = :id";
// @Cacheable(modelId="cacheModel")
 public List<User> queryForList() {
  List<User> users = this.getSimpleJdbcTemplate().query(USER_SELECT,
    new ParameterizedRowMapper<User>() {
     public User mapRow(ResultSet rs, int rowNum) throws SQLException {
      User user = new User();
      user.setId(rs.getInt(1));
      user.setUserName(rs.getString(2));
      user.setPassword(rs.getString(3));
      return user;
     }
  });
  return users;
 }
 
 private static final String USER_SELECT = "select id,username,password from user ";
 public void save(User user) {
  Map parameters = new HashMap();
  parameters.put("username", user.getUserName());
  parameters.put("password", user.getPassword());
  this.getSimpleJdbcTemplate().update(USER_INSERT, parameters);
 }
 private static final String USER_INSERT = "insert into user (username,password) values (:username, :password)";
 
}
 

我一般寫完service,都會先測試一下,我的Junit:

view plaincopy to clipboardprint?
package cn.partner4java.ehcache.service.impl;  
import java.util.List;  
import cn.partner4java.ehcache.bean.User;  
import cn.partner4java.ehcache.service.UserManageService;  
import cn.partner4java.utils.SpringContextFactory;  
import junit.framework.TestCase;  
public class UserManageServiceBeanTest extends TestCase {  
    private static UserManageService userManageService = (UserManageService) SpringContextFactory.getBean("userManageService");  
      
    public void testDeleteById() {  
        userManageService.deleteById(2);  
    }  
    public void testQueryForList() {  
        List<User> users = userManageService.queryForList();  
        System.out.print(users);  
    }  
    public void testSave() {  
        userManageService.save(new User("cache_test", "123"));  
    }  

package cn.partner4java.ehcache.service.impl;
import java.util.List;
import cn.partner4java.ehcache.bean.User;
import cn.partner4java.ehcache.service.UserManageService;
import cn.partner4java.utils.SpringContextFactory;
import junit.framework.TestCase;
public class UserManageServiceBeanTest extends TestCase {
 private static UserManageService userManageService = (UserManageService) SpringContextFactory.getBean("userManageService");
 
 public void testDeleteById() {
  userManageService.deleteById(2);
 }
 public void testQueryForList() {
  List<User> users = userManageService.queryForList();
  System.out.print(users);
 }
 public void testSave() {
  userManageService.save(new User("cache_test", "123"));
 }
}
 

我簡單寫了個jsp測試一下:

view plaincopy to clipboardprint?
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
<%@page import="cn.partner4java.ehcache.service.UserManageService"%>  
<%@page import="cn.partner4java.utils.SpringContextFactory"%>  
<%@page import="cn.partner4java.ehcache.bean.User"%>  
<%  
String path = request.getContextPath();  
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
%>  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
  <head>  
    <base href="<%=basePath%>">  
      
    <title>My JSP 'testCacheList.jsp' starting page</title>  
      
    <meta http-equiv="pragma" content="no-cache">  
    <meta http-equiv="cache-control" content="no-cache">  
    <meta http-equiv="expires" content="0">      
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    <meta http-equiv="description" content="This is my page">  
    <!--  
    <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css">  
    -->  
  </head>  
  <%  
    UserManageService userManageService = (UserManageService) SpringContextFactory.getBean("userManageService");  
    List<User> users = userManageService.queryForList();  
    out.print(users);  
   %>  
  <body>  
    This is my JSP page. <br>  
      
  </body>  
</html> 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@page import="cn.partner4java.ehcache.service.UserManageService"%>
<%@page import="cn.partner4java.utils.SpringContextFactory"%>
<%@page import="cn.partner4java.ehcache.bean.User"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
   
    <title>My JSP 'testCacheList.jsp' starting page</title>
   
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">   
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css">
 -->
  </head>
  <%
   UserManageService userManageService = (UserManageService) SpringContextFactory.getBean("userManageService");
   List<User> users = userManageService.queryForList();
   out.print(users);
   %>
  <body>
    This is my JSP page. <br>
   
  </body>
</html>
 

但是怎麼測試呢?呵呵,我就是些了一個列表,然後打開,查看,比如現在十條數據,我打開了一個mysql管理工具,刪了幾條數據,刷新這個界面還是十條數據,沒少。就驗證了緩存這點。

還有另外一種不利用spring支持的xml配置標籤和註解的形式,利用切面編程,改天再整理出來,不過,我還是很喜歡這種,所以第一時間就先搞的這個,但是有一點注意的是,包,這個利用的是springmodules項目,所以要單獨引入springmodules相關的ehcahe,的卻難找。還有,ehcache的核心包,和核心包需要的相關包。

spring-modules-cache-0.8.jar

ehcache-core-2.4.0.jar。。。

 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/aspectjrt.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/aspectjweaver.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/c3p0-0.9.1.2.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-dbcp-1.2.2.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-logging.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-pool-1.3.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/mysql-connector-java-5.1.7-bin.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/antlr-2.7.6.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/cglib-2.2.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/commons-collections-3.1.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/dom4j-1.6.1.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/hibernate3.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/javassist-3.9.0.GA.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/jta-1.1.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/log4j-1.2.15.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/spring.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-api-1.6.1.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/slf4j-jdk14-1.6.1.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/ehcache-core-2.4.0.jar"/>
 <classpathentry kind="lib" path="WebRoot/WEB-INF/lib/spring-modules-cache-0.8.jar"/>

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/partner4java/archive/2011/03/06/6227668.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章