利用Spring AOP 缓存方法结果集

阅读更多
我们都知道 Hibernate可以用ehcache来作为Second Level Cache.主要是针对POJO的缓存,而且缓存的读取
Hibernate中是写死.实际运用中感觉很不灵活.今天看到一篇介绍利用 Spring Interceptor 来缓存指定
方法结果的例子 ,感觉很不错,充分体会到AOP的强大力量 :)
首先配置 ehcache.xml
 

 

字串3

    path= "java.io.tmpdir" />
    name= "org.taha.cache.METHOD_CACHE"
        maxElementsInMemory= "300"
        eternal= "false"
        timeToIdleSeconds= "500"
        timeToLiveSeconds= "500"
        overflowToDisk= "true"
        />
 
接下在Spring配置文件中定义Ehcache组件
 
id= "cacheManager" class= "org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
  name= "configLocation" >
    classpath:ehcache.xml
 
 
id= "methodCache" class= "org.springframework.cache.ehcache.EhCacheFactoryBean" >
  name= "cacheManager" >
    local= "cacheManager" />
 
  name= "cacheName" >
    org.taha.cache.METHOD_CACHE
 
>
建立我们自己的方法拦截器 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 Znjq
  */
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 配置文件中定义拦截器
id= "methodCacheInterceptor" class= "org.taha.interceptor.MethodCacheInterceptor" >
  name= "cache" >
    local= "methodCache" />
 
 
id= "methodCachePointCut" class= "org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
  name= "advice" >
    local= "methodCacheInterceptor" />
 
  name= "patterns" >
   
      .*methodOne
      .*methodTwo
   
 
 
id= "myBean" class= "org.springframework.aop.framework.ProxyFactoryBean" >
  name= "target" >
   class= "org.taha.beans.MyBean" />
 
  name= "interceptorNames" >
   
      methodCachePointCut
   
 
这里org.springframework.aop.support.RegexpMethodPointcutAdvisor是一个正规表达式切入点,
使用Perl 5的正规表达式的语法, 基Jakarta ORO。(有空写个文档,自己研究一下).
  name= "target" >
   class= "org.taha.beans.MyBean" />
 
org.taha.beans.MyBean是我们需要做缓存处理的类.
methodCachePointCut中
.*methodOne
.*methodTwo
则是指定的模式匹配方法 , 对应于org.taha.beans.MyBean中的方法. 这里指定了2个方法需要做缓存处理.
呵呵,就是这么简单.这样每次对org.taha.beans.MyBean的 methodOne 方法进行调用 , 都会首先从缓存查找 ,
其次才会查询数据库 . 这样我就不需要在 xx.hbm.xml 来指定讨厌的 cache . 也不需要在开发阶段来关心缓存 .
一切 AOP 搞定 .. ^_^

你可能感兴趣的:(AOP,Spring,Bean,Cache,Hibernate)