spring中基于aop使用ehcache

Posted xs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于spring中基于aop使用ehcache的主要内容,如果未能解决你的问题,请参考以下文章

Spring基于注解ehCache缓存整合

spring怎么配置EHCACHE

基于注解的Spring AOP的配置和使用--转载

基于注解的Spring AOP的配置和使用--转载

Spring 基于注解配置的AOP框架详细讲解

Spring 基于注解配置的AOP框架详细讲解