我们都知道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.MyBean的methodOne方法进行调用,都会首先从缓存查找,
其次才会查询数据库. 这样我就不需要在xx.hbm.xml来指定讨厌的cache了.也不需要在开发阶段来关心缓存.
一切AOP搞定.. ^_^
转自BlogDriver,做个备份. http://znjqolf.blogdriver.com/znjqolf/429473.html