輕松

          記述我學(xué)習(xí)java的里程

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          友情鏈接

          最新評(píng)論

          利用Spring AOP 緩存方法結(jié)果集

          我們都知道Hibernate可以用ehcache來(lái)作為Second Level Cache.主要是針對(duì)POJO的緩存,而且緩存的讀取

          Hibernate中是寫(xiě)死.實(shí)際運(yùn)用中感覺(jué)很不靈活.今天看到一篇介紹利用Spring Interceptor 來(lái)緩存指定

          方法結(jié)果的例子,感覺(jué)很不錯(cuò),充分體會(huì)到AOP的強(qiáng)大力量 :)

          首先配置ehcache.xml

           <ehcache>

              <diskStore path="java.io.tmpdir"/>

              <cache name="org.taha.cache.METHOD_CACHE"

                  maxElementsInMemory="300"

                  eternal="false"

                  timeToIdleSeconds="500"

                  timeToLiveSeconds="500"

                  overflowToDisk="true"

                  />

          </ehcache>

           

          接下在Spring配置文件中定義Ehcache組件

           

          <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

            <property name="configLocation">

              <value>classpath:ehcache.xml</value>

            </property>

          </bean>

           

          <bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">

            <property name="cacheManager">

              <ref local="cacheManager"/>

            </property>

            <property name="cacheName">

              <value>org.taha.cache.METHOD_CACHE</value>

            </property>

          </bean>

          建立我們自己的方法攔截器MethodCacheInterceptor.

          MethodCacheInterceptor實(shí)現(xiàn)了org.aopalliance.intercept.MethodInterceptor接口.

          import java.io.Serializable;

           

          import net.sf.ehcache.Cache;

          import net.sf.ehcache.Element;

           

          import org.aopalliance.intercept.MethodInterceptor;

          import org.aopalliance.intercept.MethodInvocation;

          import org.springframework.beans.factory.InitializingBean;

           

          /**

           * 攔截器,用于緩存方法返回結(jié)果.

           *

           * @version $Id: MethodCacheInterceptor.java v 1.0 2004-11-28 14:57:00 Znjq Exp $

           * @author <a href="mailto:znjq1980@etang.com">Znjq </a>

           */

          public class MethodCacheInterceptor implements MethodInterceptor,

                  InitializingBean {

              private Cache cache;

           

              /**

               * sets cache name to be used

               */

              public void setCache(Cache cache) {

                  this.cache = cache;

              }

           

              /*

               * (non-Javadoc)

               *

               * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)

               */

              public Object invoke(MethodInvocation invocation) throws Throwable {

                 String targetName = invocation.getThis().getClass().getName();

                  String methodName = invocation.getMethod().getName();

                  Object[] arguments = invocation.getArguments();

                  Object result;

           

                  String cacheKey = getCacheKey(targetName, methodName, arguments);

                  Element element = cache.get(cacheKey);

                  if (element == null) {

                      //call target/sub-interceptor

                      result = invocation.proceed();

           

                      //cache method result

                      element = new Element(cacheKey, (Serializable) result);

                      cache.put(element);

                  }

                  return element.getValue();

              }

           

              /**

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

               */

              private String getCacheKey(String targetName, String methodName,

                      Object[] arguments) {

                  StringBuffer sb = new StringBuffer();

                  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();

              }

           

              /*

               * (non-Javadoc)

               *

               * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()

               */

              public void afterPropertiesSet() throws Exception {

                  // TODO Auto-generated method stub

           

              }

          }

          invoke方法中,首先根據(jù)key查詢緩存(key=className + methodName + arguments)

          ,緩存中存在則返回,否之調(diào)用invocation.proceed()返回結(jié)果.

          Spring配置文件中定義攔截器

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

          這里org.springframework.aop.support.RegexpMethodPointcutAdvisor是一個(gè)正規(guī)表達(dá)式切入點(diǎn),

          使用Perl 5的正規(guī)表達(dá)式的語(yǔ)法, Jakarta ORO(有空寫(xiě)個(gè)文檔,自己研究一下).

            <property name="target">

             <bean class="org.taha.beans.MyBean"/>

            </property>

          org.taha.beans.MyBean是我們需要做緩存處理的類.

          methodCachePointCut

          <value>.*methodOne</value>

          <value>.*methodTwo</value>

          則是指定的模式匹配方法,對(duì)應(yīng)于org.taha.beans.MyBean中的方法. 這里指定了2個(gè)方法需要做緩存處理.

          呵呵,就是這么簡(jiǎn)單.這樣每次對(duì)org.taha.beans.MyBeanmethodOne方法進(jìn)行調(diào)用,都會(huì)首先從緩存查找,

          其次才會(huì)查詢數(shù)據(jù)庫(kù). 這樣我就不需要在xx.hbm.xml來(lái)指定討厭的cache.也不需要在開(kāi)發(fā)階段來(lái)關(guān)心緩存.

          一切AOP搞定.. ^_^

          posted on 2005-04-11 15:17 輕松 閱讀(4243) 評(píng)論(3)  編輯  收藏 所屬分類: JAVA轉(zhuǎn)貼

          評(píng)論

          # re: 利用Spring AOP 緩存方法結(jié)果集 2006-11-28 10:08 Tang Anping

          踏破鐵鞋無(wú)覓處,得來(lái)全不費(fèi)工夫。
          一下子,這幾天的難題都解決了,謝謝!
          有一個(gè)小問(wèn)題,好像使用默認(rèn)的cglib會(huì)報(bào)錯(cuò),設(shè)置target即可。  回復(fù)  更多評(píng)論   

          # re: 利用Spring AOP 緩存方法結(jié)果集 2008-11-27 17:00 ww

          如何對(duì)ModelAndView進(jìn)行緩存啊  回復(fù)  更多評(píng)論   

          # re: 利用Spring AOP 緩存方法結(jié)果集 2010-08-29 08:05 lwq

          沒(méi)有大小設(shè)定嗎?
          會(huì)不會(huì)導(dǎo)致內(nèi)存溢出?  回復(fù)  更多評(píng)論   

          主站蜘蛛池模板: 衡南县| 阿克陶县| 遵义市| 海晏县| 铜山县| 美姑县| 台东县| 久治县| 定安县| 桂林市| 南通市| 馆陶县| 吐鲁番市| 嵊泗县| 香河县| 马尔康县| 西充县| 响水县| 格尔木市| 郁南县| 克东县| 吴堡县| 新沂市| 宜城市| 乌恰县| 陵川县| 沁阳市| 水富县| 右玉县| 奉化市| 雅江县| 长沙县| 阳朔县| 错那县| 呼图壁县| 陵水| 洛川县| 兴义市| 青阳县| 朝阳区| 泾阳县|