SPRING AOP的EHCACHE

SPRING AOP的EHCACHE

最近根据网上的文章配置了一个面向应用的EHCACHE,发现使用起来很方便。
只要是继承了这个CACHE的配置,那么自动会拦截GET和FIND等方法来做CACHE
下载ehcache包这些就不用说了。
ehcache.xml文件配置如下,这个不用做多少改动:
<ehcache>
<diskStore path="c:\\temp\\cache"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.

The following attributes are required:

maxElementsInMemory - Sets the maximum number of objects that will be created in

memory
eternal - Sets whether elements are eternal. If eternal, timeouts are

ignored and the
element is never expired.
overflowToDisk - Sets whether elements can overflow to disk when the in-memory

cache
has reached the maxInMemory limit.

The following attributes are optional:
timeToIdleSeconds - Sets the time to idle for an element before it expires.
i.e. The maximum amount of time between accesses before an

element expires
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that an Element can idle

for infinity.
The default value is 0.
timeToLiveSeconds - Sets the time to live for an element before it expires.
i.e. The maximum time between creation time and when an element

expires.
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that and Element can

live for infinity.
The default value is 0.
diskPersistent - Whether the disk store persists between restarts of the Virtual

Machine.
The default value is false.
diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread.

The default value
is 120 seconds.
-->
<cache name="DEFAULT_CACHE"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300000"
timeToLiveSeconds="600000"
overflowToDisk="true"
/>
</ehcache>

需要做CACHE的servers这么配置,这是我的applicationContext-core-service.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName" default-lazy-init="true">
<bean id="userManager" parent="baseTxService">
<property name="target">
<bean
class="com.sillycat.core.service.impl.UserManagerImpl" />
</property>
</bean>
</beans>

拦截方法做cache的配置主要就在这个baseTxService上面,我把事务拦截也放在这里了,
applicationContext-transaction.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="baseTxService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="proxyTargetClass" value="true" />
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="preInterceptors">
<list>
<ref bean="methodCachePointCut" />
<ref bean="methodCachePointCutAdvice"/>
</list>
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
</beans>

这里面的两个拦截的bean,methodCachePointCut和methodCachePointCutAdvice专门放置到一个文件中配置,
applicationContext-cache.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 引用ehCache的配置 -->
<bean id="defaultCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>classpath:ehcache.xml</value>
</property>
</bean>

<!-- 定义ehCache的工厂,并设置所使用的Cache name -->
<bean id="ehCache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="defaultCacheManager" />
</property>
<property name="cacheName">
<value>DEFAULT_CACHE</value>
</property>
</bean>

<!-- find/create cache拦截器 -->
<bean id="methodCacheInterceptor"
class="com.sillycat.plugin.cache.interceptors.MethodCacheInterceptor">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>
<!-- flush cache拦截器 -->
<bean id="methodCacheAfterAdvice"
class="com.sillycat.plugin.cache.interceptors.MethodCacheAfterAdvice">
<property name="cache">
<ref local="ehCache" />
</property>
</bean>

<bean id="methodCachePointCut"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="methodCacheInterceptor" />
</property>
<property name="patterns">
<list>
<value>.*find.*</value>
<value>.*get.*</value>
</list>
</property>
</bean>
<bean id="methodCachePointCutAdvice"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="methodCacheAfterAdvice" />
</property>
<property name="patterns">
<list>
<value>.*create.*</value>
<value>.*save.*</value>
<value>.*insert.*</value>
<value>.*update.*</value>
<value>.*delete.*</value>
<value>.*remove.*</value>
</list>
</property>
</bean>
</beans>

如上所配置,只要继承了这个配置的service,里面的find get方法就会先走cache,另外,当发生

create,save,insert,update
delete,remove等方法时,就会去flush一下。

另外,两个类也贴出来,MethodCacheAfterAdvice.java:
package com.sillycat.plugin.cache.interceptors;

import java.util.List;

import net.sf.ehcache.Cache;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.beans.factory.InitializingBean;

public class MethodCacheAfterAdvice implements AfterReturningAdvice,
InitializingBean {
private static final Log logger = LogFactory
.getLog(MethodCacheAfterAdvice.class);

private Cache cache;

public void setCache(Cache cache) {
this.cache = cache;
}

public MethodCacheAfterAdvice() {
super();
}

public void afterPropertiesSet() throws Exception {

}

public void afterReturning(Object returnValue,
java.lang.reflect.Method method, Object[] args, Object classObj)
throws Throwable {
String className = classObj.getClass().getName();
List list = cache.getKeys();
for (int i = 0; i < list.size(); i++) {
String cacheKey = String.valueOf(list.get(i));
if (cacheKey.startsWith(className)) {
cache.remove(cacheKey);
logger.debug("remove cache " + cacheKey);
}
}

}

}


MethodCacheInterceptor.java如下:
package com.sillycat.plugin.cache.interceptors;

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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;

public class MethodCacheInterceptor implements MethodInterceptor,
InitializingBean {
private static final Log logger = LogFactory
.getLog(MethodCacheInterceptor.class);

private Cache cache;

public void setCache(Cache cache) {
this.cache = cache;
}

public MethodCacheInterceptor() {
super();
}

/**
*
*
* 拦截Service/DAO的方法,并查找该结果是否存在,如果存在就返回cache中的值, 否则,返回数据库查询

结果,并将查询结果放入cache
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
String targetName = invocation.getThis().getClass().getName();
String methodName = invocation.getMethod().getName();
Object[] arguments = invocation.getArguments();
Object result;

logger.debug("Find object from cache is " + cache.getName());

String cacheKey = getCacheKey(targetName, methodName, arguments);
Element element = cache.get(cacheKey);

if (element == null) {
logger
.debug("Hold up method , Get method result and create

cache........!");
result = invocation.proceed();
element = new Element(cacheKey, (Serializable) result);
cache.put(element);
}
return element.getValue();
}

/**
*
*
* 获得cache key的方法,cache key是Cache中一个Element的唯一标识 cache key包括
* 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser
*/
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();
}

/**
*
*
* implement InitializingBean,检查cache是否为空
*/
public void afterPropertiesSet() throws Exception {

}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值