首页 > 代码库 > spring中基于aop使用ehcache

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="http://www.mamicode.com/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="http://www.mamicode.com/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="http://www.mamicode.com/testDao", key="‘view‘ + #id")*/public testInfo getInfo(String id) {         return (testInfo) sessionFactory.getCurrentSession().get(testInfo.class, id);} /**@Caching(    put={@CachePut(value="http://www.mamicode.com/testDao", key="‘view‘ + #testInfo.id")},     evict={@CacheEvict(value="http://www.mamicode.com/testDao", key="‘list‘")})*/public testInfo update(testInfo testInfo) {    testInfo.setName("789");    //update    return testInfo;} /**@Caching(     evict={        @CacheEvict(value="http://www.mamicode.com/testDao", key="‘view‘ + #id"),         @CacheEvict(value="http://www.mamicode.com/testDao", key="‘list‘")})*/public void delete(String id) {    //delete} /**@CacheEvict(value="http://www.mamicode.com/testDao", allEntries=true)*/public void deleteAll() {    //deleteAll}

 

2、测试

第一次访问"http://localhost:8080/demo1/hello/list2"地址,进入增加缓存的环绕通知,然后执行方法,将结果存入缓存

技术分享

 

第二次访问的时候,缓存里就有数据了,可以直接用,不用再执行方法

技术分享

 

点击"删除"按钮,会进入移除缓存的后置通知,然后匹配实例名,删除list的缓存

技术分享

 

实例代码地址:https://github.com/ctxsdhy/cnblogs-example

 

spring中基于aop使用ehcache