spring中基于aop使用ehcache
继续上篇,这篇介绍服务层缓存,基于aop的方式使用ehcache
一、修改配置文件
修改spring-context-ehcache.xml文件,加入:
<!-- ehcache缓存实例 --> <bean id="testCacheInterceptor" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager" ref="ehcacheManager"/> <property name="cacheName" value="aopTestDao" /> </bean> <!-- 要织入的通知(切面) --> <bean id="testCache" class="org.xs.demo1.CacheInterceptor"> <!-- 传入ehcache缓存实例 --> <property name="cache" ref="testCacheInterceptor" /> </bean> <!-- AOP配置 --> <aop:config> <!-- 定义切面 --> <aop:aspect ref="testCache"> <!-- 定义增加缓存的切点 --> <aop:pointcut id="testAddCache" expression="execution(* org.xs.demo1.testDao.get*(..))" /> <!-- 定义环绕通知 --> <aop:around pointcut-ref="testAddCache" method="addCache" /> <!-- 定义移除缓存的切点 --> <aop:pointcut id="testRemoveCache" expression="execution(* org.xs.demo1.testDao.update*(..)) || execution(* org.xs.demo1.testDao.delete*(..))" /> <!-- 定义后置通知 --> <aop:after pointcut-ref="testRemoveCache" method="removeCache" /> </aop:aspect> </aop:config>
在ehcache-context.xml中也可以加入cacheName为"aopTestDao"的缓存实例配置
二、增加缓存操作拦截器
在"src/main/java"代码文件夹的"org.xs.demo1"的包下新建"CacheInterceptor.java"类:
package org.xs.demo1; import java.io.Serializable; import java.util.List; import net.sf.ehcache.Cache; import net.sf.ehcache.Element; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; /** * 缓存操作拦截器 */ public class CacheInterceptor { /** * 缓存实例 */ private Cache cache; public Cache getCache() { return cache; } public void setCache(Cache cache) { this.cache = cache; } /** * 增加缓存 */ public Object addCache(ProceedingJoinPoint joinpoint) { Object result = null; try { //组合缓存key(实例名,方法名,方法参数列表) String cacheKey = getCacheKey(joinpoint.getTarget().getClass().getName(), joinpoint.getSignature().getName(), joinpoint.getArgs()); Element element = cache.get(cacheKey); //如果缓存里有就从缓存里取 if(element != null) { result = element.getObjectValue(); } else { //执行方法,获得结果 result = joinpoint.proceed(); //将结果存入缓存 cache.put(new Element(cacheKey, (Serializable)result)); } } catch (Throwable e) { e.printStackTrace(); } return result; } /** * 移除缓存 */ public void removeCache(JoinPoint point) { //获得实例名 String className = point.getTarget().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); } } } /** * 组合缓存key */ 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++) { if(arguments[i] instanceof String[]){ String[] strArray = (String[])arguments[i]; sb.append("."); for(String str : strArray){ sb.append(str); } }else{ sb.append(".").append(arguments[i]); } } } return sb.toString(); } }
三、运行测试
1、先注释之前testDao里的ehcache注释,不然看不到效果
@SuppressWarnings("unchecked") /**@Cacheable(value="testDao", key="'list'")*/ public List<testInfo> getList() { String hql = "from testInfo"; Query query = sessionFactory.getCurrentSession().createQuery(hql); query.setCacheable(true); return query.list(); } /**@Cacheable(value="testDao", key="'view' + #id")*/ public testInfo getInfo(String id) { return (testInfo) sessionFactory.getCurrentSession().get(testInfo.class, id); } /**@Caching( put={@CachePut(value="testDao", key="'view' + #testInfo.id")}, evict={@CacheEvict(value="testDao", key="'list'")} )*/ public testInfo update(testInfo testInfo) { testInfo.setName("789"); //update return testInfo; } /**@Caching( evict={ @CacheEvict(value="testDao", key="'view' + #id"), @CacheEvict(value="testDao", key="'list'")} )*/ public void delete(String id) { //delete } /**@CacheEvict(value="testDao", allEntries=true)*/ public void deleteAll() { //deleteAll }
2、测试
第一次访问"http://localhost:8080/demo1/hello/list2"地址,进入增加缓存的环绕通知,然后执行方法,将结果存入缓存
第二次访问的时候,缓存里就有数据了,可以直接用,不用再执行方法
点击"删除"按钮,会进入移除缓存的后置通知,然后匹配实例名,删除list的缓存
实例代码地址:https://github.com/ctxsdhy/cnblogs-example