輕松

          記述我學習java的里程

          常用鏈接

          統(tǒng)計

          積分與排名

          友情鏈接

          最新評論

          利用Spring AOP 緩存方法結果集

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

          Hibernate中是寫死.實際運用中感覺很不靈活.今天看到一篇介紹利用Spring Interceptor 來緩存指定

          方法結果的例子,感覺很不錯,充分體會到AOP的強大力量 :)

          首先配置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實現(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;

           

          /**

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

           *

           * @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()返回結果.

          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是一個正規(guī)表達式切入點,

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

            <property name="target">

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

            </property>

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

          methodCachePointCut

          <value>.*methodOne</value>

          <value>.*methodTwo</value>

          則是指定的模式匹配方法,對應于org.taha.beans.MyBean中的方法. 這里指定了2個方法需要做緩存處理.

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

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

          一切AOP搞定.. ^_^

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

          評論

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

          踏破鐵鞋無覓處,得來全不費工夫。
          一下子,這幾天的難題都解決了,謝謝!
          有一個小問題,好像使用默認的cglib會報錯,設置target即可。  回復  更多評論   

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

          如何對ModelAndView進行緩存啊  回復  更多評論   

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

          沒有大小設定嗎?
          會不會導致內(nèi)存溢出?  回復  更多評論   

          主站蜘蛛池模板: 凭祥市| 和政县| 张掖市| 济源市| 德州市| 恩平市| 安达市| 德令哈市| 新兴县| 福清市| 团风县| 临潭县| 肃北| 岚皋县| 枝江市| 西和县| 江陵县| 托克逊县| 日喀则市| 宝应县| 比如县| 桃园市| 连城县| 渝北区| 屏东市| 大城县| 星子县| 永新县| 潼关县| 天柱县| 弥渡县| 郁南县| 来凤县| 高唐县| 甘南县| 怀柔区| 兴仁县| 安庆市| 庄浪县| 岳阳县| 营口市|