捕風(fēng)之巢

          統(tǒng)計(jì)

          • 隨筆 - 7
          • 文章 - 82
          • 評(píng)論 - 14
          • 引用 - 0

          留言簿(3)

          java友情鏈接

          閱讀排行榜

          評(píng)論排行榜

          Caching the result of methods using Spring and EHCache

          by:http://opensource.atlassian.com/confluence/spring/display/DISC/Caching+the+result+of+methods+using+Spring+and+EHCache

          Introduction

          Spring 1.1.1 introduced integration for EHCache for general cache use.

          I will show here a sample Interceptor that allows for declarative caching of methods results.

          Configure EHCache using Spring IoC

          Spring makes EHCache configuration very easy. All you need, is to provide a ehcache.xml file where you configure EHCache regions:

          <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.

          ????????
          -->

          ????
          <cache?name="org.taha.cache.METHOD_CACHE"
          ????????maxElementsInMemory
          ="300"
          ????????eternal
          ="false"
          ????????timeToIdleSeconds
          ="500"
          ????????timeToLiveSeconds
          ="500"
          ????????overflowToDisk
          ="true"
          ????????
          />
          </ehcache>

          Our Interceptor will use region "org.taha.cache.METHOD_CACHE" to cache methods results.
          Now we will use some Spring IoC to make this region accessible to our beans:

          <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.

          ????????
          -->

          ????
          <cache?name="org.taha.cache.METHOD_CACHE"
          ????????maxElementsInMemory
          ="300"
          ????????eternal
          ="false"
          ????????timeToIdleSeconds
          ="500"
          ????????timeToLiveSeconds
          ="500"
          ????????overflowToDisk
          ="true"
          ????????
          />
          </ehcache>

          Bean methodCache creates cache region org.taha.cache.METHOD_CACHE.

          Creating our MethodCacheInterceptor

          The interceptor implements org.aopalliance.intercept.MethodInterceptor. Whenever it kicks-in, it first checks if the intercepted method is configured to be cached. This allows to selectively configure bean methods for caching. If the method call is configured for caching, the interceptor builds the cache key for the method and checks if the method result is in the cache. If so, the cached result is returned, otherwise the intercepted method is called and the result cached for further use.

          org.taha.interceptor.MethodCacheInterceptor
          /*
          ?*?Copyright?2002-2004?the?original?author?or?authors.
          ?*
          ?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");
          ?*?you?may?not?use?this?file?except?in?compliance?with?the?License.
          ?*?You?may?obtain?a?copy?of?the?License?at
          ?*
          ?*??????
          http://www.apache.org/licenses/LICENSE-2.0
          ?*
          ?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software
          ?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,
          ?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.
          ?*?See?the?License?for?the?specific?language?governing?permissions?and
          ?*?limitations?under?the?License.
          ?
          */


          package?org.taha.interceptor;

          import?java.io.Serializable;

          import?org.aopalliance.intercept.MethodInterceptor;
          import?org.aopalliance.intercept.MethodInvocation;

          import?org.apache.commons.logging.LogFactory;
          import?org.apache.commons.logging.Log;

          import?org.springframework.beans.factory.InitializingBean;
          import?org.springframework.util.Assert;

          import?net.sf.ehcache.Cache;
          import?net.sf.ehcache.Element;

          /**
          ?*?
          @author?<a?href="mailto:irbouh@gmail.com">Omar?Irbouh</a>
          ?*?
          @since?2004.10.07
          ?
          */

          public?class?MethodCacheInterceptor?implements?MethodInterceptor,?InitializingBean?{
          ??privatestaticfinal?Log?logger?
          =?LogFactory.getLog(MethodCacheInterceptor.class);

          ??
          private?Cache?cache;

          ??
          /**
          ???*?sets?cache?name?to?be?used
          ???
          */

          ??
          public?void?setCache(Cache?cache)?{
          ????
          this.cache?=?cache;
          ??}


          ??
          /**
          ???*?Checks?if?required?attributes?are?provided.
          ???
          */

          ??
          public?void?afterPropertiesSet()?throws?Exception?{
          ????Assert.notNull(cache,?
          "A?cache?is?required.?Use?setCache(Cache)?to?provide?one.");
          ??}


          ??
          /**
          ???*?main?method
          ???*?caches?method?result?if?method?is?configured?for?caching
          ???*?method?results?must?be?serializable
          ???
          */

          ??publicObject?invoke(MethodInvocation?invocation)?
          throws?Throwable?{
          ????String?targetName??
          =?invocation.getThis().getClass().getName();
          ????String?methodName??
          =?invocation.getMethod().getName();
          ????Object[]?arguments?
          =?invocation.getArguments();
          ????Object?result;

          ????logger.debug(
          "looking?for?method?result?in?cache");
          ????String?cacheKey?
          =?getCacheKey(targetName,?methodName,?arguments);
          ????Element?element?
          =?cache.get(cacheKey);
          ????
          if?(element?==?null)?{
          ??????
          //call?target/sub-interceptor
          ??????logger.debug("calling?intercepted?method");
          ??????result?
          =?invocation.proceed();

          ??????
          //cache?method?result
          ??????logger.debug("caching?result");
          ??????element?
          =?new?Element(cacheKey,?(Serializable)?result);
          ??????cache.put(element);
          ????}

          ????
          return?element.getValue();
          ??}


          ??
          /**
          ???*?creates?cache?key:?targetName.methodName.argument0.argument1
          ???
          */

          ??privateString?getCacheKey(String?targetName,
          ?????????????????????????????String?methodName,
          ?????????????????????????????Object[]?arguments)?
          {
          ????StringBuffer?sb?
          =?newStringBuffer();
          ????sb.append(targetName)
          ??????.append(
          ".").append(methodName);
          ????
          if?((arguments?!=?null)?&&?(arguments.length?!=?0))?{
          ??????
          for?(int?i=0;?i<arguments.length;?i++)?{
          ????????sb.append(
          ".")
          ??????????.append(arguments[i]);
          ??????}

          ????}


          ????
          return?sb.toString();
          ??}

          }
          MethodCacheInterceptor source shows that:
          • by default, all methods result are cached (methodNames is null)
          • cache region is configured using IoC
          • cacheKey takes in consideration method arguments

          Using MethodCacheInterceptor

          The following excerpt shows how to configure MethodCacheInterceptor:

          <bean?id="methodCacheInterceptor"?class="org.taha.interceptor.MethodCacheInterceptor">
          ??
          <property?name="cache">
          ????
          <ref?local="methodCache"?/>
          ??
          </property>
          </bean>

          <bean?id="methodCachePointCut"?class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
          ??
          <property?name="advice">
          ????
          <ref?local="methodCacheInterceptor"/>
          ??
          </property>
          ??
          <property?name="patterns">
          ????
          <list>
          ??????
          <value>.*methodOne</value>
          ??????
          <value>.*methodTwo</value>
          ????
          </list>
          ??
          </property>
          </bean>

          <bean?id="myBean"?class="org.springframework.aop.framework.ProxyFactoryBean">
          ??
          <property?name="target">
          ???
          <bean?class="org.taha.beans.MyBean"/>
          ??
          </property>
          ??
          <property?name="interceptorNames">
          ????
          <list>
          ??????
          <value>methodCachePointCut</value>
          ????
          </list>
          ??
          </property>
          </bean>
          Further improvements:

          It will be very helpfull to add the following to MethodCacheInterceptor:

          • refactor the code so that the interceptor no longer depends on EHCache
          • add arguments to methods configuration:
            <property?name="methodNames">
            ??
            <list>
            ????
            <value>methodOne(java.lang.String,?int)</value>
            ????
            <value>methodOne(java.lang.String,?java.lang.String)</value>
            ??
            </list>
            </property>
          • add regular expressions to method configuration
            <property?name="methodNames">
            ??
            <list>
            ????
            <value>add*</value>
            ??
            </list>
            </property>

          Changes:

          • MethodCacheInterceptor now implements InitializingBean
          • removed property methodNames and setter setMethodNames(java.lang.String)
          • MethodCacheInterceptor can be configured using regular PointCutAdvisor
          • using org.springframework.util.Assert to eagerly check if property cache is not null

          posted on 2006-10-11 11:27 捕風(fēng) 閱讀(397) 評(píng)論(0)  編輯  收藏 所屬分類: java高級(jí)

          主站蜘蛛池模板: 晋中市| 丹阳市| 陵川县| 石渠县| 肥东县| 庆阳市| 容城县| 祁阳县| 乐至县| 青铜峡市| 瑞昌市| 万州区| 嘉黎县| 乌苏市| 通河县| 郧西县| 招远市| 友谊县| 出国| 阳原县| 商南县| 正宁县| 荥阳市| 射阳县| 咸阳市| 鱼台县| 陵川县| 绵阳市| 门头沟区| 宕昌县| 永定县| 洛川县| 北票市| 南岸区| 英吉沙县| 汉沽区| 吉安县| 上思县| 明星| 凌源市| 镶黄旗|