AOP+Ehcache 实现缓存功能
AOP+Ehcache 实现缓存功能
1.需要引入AOP和Ehcache相关Jar文件
2.编写切面类里面写上拦截时的业务逻辑
package com.berheley.bi.aop;import java.io.Serializable;import java.util.List;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;import org.springframework.util.Assert;/** * * 类功能描述:AOP+Ehcache 拦截需要缓存的方法,插入点方法执行前后 * * @author <a href="mailto:qingyu.meng21@gmail.com">mengqingyu </a> * @version $Id: codetemplates.xml,v 1.1 2009/03/06 01:13:01 mengqingyu Exp $ * Create: 2011-12-12 下午04:27:44 */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 */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object result; String cacheKey = getCacheKey(invocation.getThis().getClass().getName() , invocation.getMethod().getName(), invocation.getArguments()); Element element = cache.get(cacheKey); logger.warn("检查缓存:" + cacheKey); if (element == null) { logger.warn("创建缓存......"); result = invocation.proceed(); element = new Element(cacheKey, (Serializable) result); cache.put(element); } List list = cache.getKeys(); return element.getValue(); } /** * * @function:获得cache key的方法,cache key是Cache中一个Element的唯一标识 * cache key包括 包名+类名+方法名,如com.co.cache.service.UserServiceImpl.getAllUser * @param targetName * @param methodName * @param arguments * @return * @author: mengqingyu 2011-12-12 下午04:35:21 */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuilder sb = new StringBuilder(); sb.append(targetName).append(".").append(methodName); if (arguments != null) { for(Object o:arguments){ sb.append(".").append(o); } } return sb.toString(); } /** * implement InitializingBean,检查cache是否为空 */ public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "缓存未初始化"); }}package com.berheley.bi.aop;import java.lang.reflect.Method;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;import org.springframework.util.Assert;/** * * 类功能描述:AOP+Ehcache 拦截需要缓存的方法,插入点方法执行之后 * * @author <a href="mailto:qingyu.meng21@gmail.com">mengqingyu </a> * @version $Id: codetemplates.xml,v 1.1 2009/03/06 01:13:01 mengqingyu Exp $ * Create: 2011-12-12 下午04:27:44 */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(); } /** * 拦截Service/DAO的方法,并查找该结果是否存在,如果存在则删除结果, * 否则忽略,此方法为了保证更新数据库同时同步缓存 */ @Overridepublic void afterReturning(Object arg, Method method, Object[] arguments,Object obj) throws Throwable {String className = obj.getClass().getName();List<String> list = cache.getKeys();for(String cacheKey:list){if(cacheKey.startsWith(className)){cache.remove(cacheKey);logger.debug("删除缓存:" + cacheKey);}}} /** * implement InitializingBean,检查cache是否为空 */ public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "缓存未初始化"); }}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd "><!-- AOP+Ehcache by mengqingyu--><!-- 引用ehCache的配置 --><bean id="defaultCacheManager" /> </property></bean><!-- find/create cache拦截器 --><bean id="methodCacheAfterAdvice" /> </property></bean><!-- 自动代理 --><aop:config><!-- 这里可添加多个切入点 --><aop:advisor pointcut="execution(* com.berheley.bi.report.service.impl.SummaryReportServiceImpl.getSource*(..))" advice-ref="methodCacheInterceptor" /><aop:advisor pointcut="execution(* com.berheley.bi.report.service.impl.SummaryReportServiceImpl.getPrefixAndSuffix*(..))" advice-ref="methodCacheAfterAdvice" /></aop:config></beans>
<!-- AOP+Ehcache by mengqingyu--><!-- diskStore 当内存缓存数量超过设置数量时,将数据写到硬盘中,path为硬盘相对路径 maxElementsInMemory 缓存中最大允许创建的对象数eternal 缓存中对象是否为永久,如果true过期设置将无效 timeToIdleSeconds 自最后读取开始有效时间 timeToLiveSeconds 自创建开始有效时间overflowToDisk 内存不足时是否启用磁盘缓存 --><ehcache><diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false" diskExpiryThreadIntervalSeconds="120"/> <cache name="systemCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="259200000" timeToLiveSeconds="259200000" overflowToDisk="true"/> </ehcache>