轻松

记述我学习java的里程

常用链接

统计

积分与排名

友情链接

最新评论

利用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实现了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方法中,首先根据key查询缓存(key=className + methodName + arguments)

,缓存中存在则返回,否之调用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是一个正规表达式切入点,

使用Perl 5的正规表达式的语法, 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方法进行调用,都会首先从缓存查找,

其次才会查询数据库. 这样我就不需要在xx.hbm.xml来指定讨厌的cache.也不需要在开发阶段来关心缓存.

一切AOP搞定.. ^_^

posted on 2005-04-11 15:17 轻松 阅读(4236) 评论(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

没有大小设定吗?
会不会导致内存溢出?  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: