Spring AOP+EHCache简单缓存系统解决方案

需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系统中Service或则DAO层的get/find等方法返回结果,如果数据更新(使用Create/update/delete方法),则刷新cache中相应的内容。 MethodCacheInterceptor.java

Java代码 
package com.co.cache.ehcache;    
   
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;    
import org.springframework.util.Assert;    
   
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 {    
        Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");    
    }    
   

上面的代码中可以看到,在方法public Object invoke(MethodInvocation invocation) 中,完成了搜索Cache/新建cache的功能。

Java代码 
Element element = cache.get(cacheKey);

这句代码的作用是获取cache中的element,如果cacheKey所对应的element不存在,将会返回一个null值

Java代码 
result = invocation.proceed(); 

这句代码的作用是获取所拦截方法的返回值,详细请查阅AOP相关文档。

随后,再建立一个拦截器MethodCacheAfterAdvice,作用是在用户进行create/update/delete操作时来刷新/remove相关cache内容,这个拦截器实现了AfterReturningAdvice接口,将会在所拦截的方法执行后执行在public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3)方法中所预定的操作

Java代码 
package com.co.cache.ehcache;    
   
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;    
   
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 afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {    
        String className = arg3.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);    
            }    
        }    
    }    
   
    public void afterPropertiesSet() throws Exception {    
        Assert.notNull(cache, "Need a cache. Please use setCache(Cache) create it.");    
    }    
   
}

上面的代码很简单,实现了afterReturning方法实现自AfterReturningAdvice接口,方法中所定义的内容将会在目标方法执行后执行,在该方法中

Java代码 
String className = arg3.getClass().getName(); 


的作用是获取目标class的全名,如:com.co.cache.test.TestServiceImpl,然后循环cache的key list,remove cache中所有和该class相关的element。

随后,开始配置ehCache的属性,ehCache需要一个xml文件来设置ehCache相关的一些属性,如最大缓存数量、cache刷新的时间等等. 
ehcache.xml

Java代码 
<ehcache>    
    <diskStore path="c:\\myapp\\cache"/>    
    <defaultCache    
        maxElementsInMemory="1000"   
        eternal="false"   
        timeToIdleSeconds="120"   
        timeToLiveSeconds="120"   
        overflowToDisk="true"   
        />    
<cache name="DEFAULT_CACHE"   
        maxElementsInMemory="10000"   
        eternal="false"   
        timeToIdleSeconds="300000"   
        timeToLiveSeconds="600000"   
        overflowToDisk="true"   
        />    
</ehcache>

 

转Spring+Hibernate+EHcache配置(二)的更多相关文章

  1. 【转】Spring+Hibernate+EHcache配置(一)

    大量数据流动是web应用性能问题常见的原因,而缓存被广泛的用于优化数据库应用.cache被设计为通过保存从数据库里load的数据来减少应用和数据库之间的数据流动.数据库访问只有当检索的数据不在cach ...

  2. 转Spring+Hibernate+EHcache配置(三)

    配置每一项的详细作用不再详细解释,有兴趣的请google下 ,这里需要注意一点defaultCache标签定义了一个默认的Cache,这个Cache是不能删除的,否则会抛出No default cac ...

  3. Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作

    详细的Spring MVC框架搭配在这个连接中: Maven 工程下 Spring MVC 站点配置 (一) Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作 这篇主 ...

  4. Spring+Hibernate整合配置 --- 比较完整的spring、hibernate 配置

    Spring+Hibernate整合配置 分类: J2EE2010-11-25 17:21 16667人阅读 评论(1) 收藏 举报 springhibernateclassactionservlet ...

  5. 笔记59 Spring+Hibernate整合(二)

    一.项目结构 二.创建表 数据库中只有一张表,stock,三个字段:stock_id.stock_code和stock_name. CREATE TABLE `stock` ( `STOCK_ID` ...

  6. Spring Security认证配置(二)

    学习本章之前,可以先了解下上篇Spring Security基本配置. 本篇想要达到这样几个目的: 1.访问调用者服务时,如果是html请求,则跳转到登录页,否则返回401状态码和错误信息 2.调用方 ...

  7. Hibernate+EhCache配置二级缓存

    步骤: 第一步:加入ehcache.jar 第二步: 在src目录下新建一个文件,名为:ehcache.xml 第三步:在hibernate配置文件的<session-factory>下配 ...

  8. SSH(Struts+spring+hibernate)配置

    1.spring和struts 1)web.xml 配置spring的ContextLoaderListener(监听器) 配置Struts的StrutsPrepareAndExecuteFilter ...

  9. Maven搭建struts2+spring+hibernate环境

    Maven搭建struts2+spring+hibernate环境(一) 本文简单的使用STS的自带的maven插件工具搭建ssh(struts2+spring+hibernate)开发环境,图文并茂 ...

随机推荐

  1. android 使用两个surfaceview 在摄像机画面上绘图

    转载自http://blog.csdn.net/jesse__zhong/article/details/24934083 使用双surface,将第一个设置为透明背景,在摄像机上绘制图像,纠结搞了一 ...

  2. 剑指offer_快速查找递增二维数组中是否存在目标

    [编程题]二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数     ...

  3. python的全局变量玩法还挺特别的

    global g_arr def add(): #global g_arr g_arr = [] g_arr.append(1) add() print g_arr #你将收获一个NameError错 ...

  4. PHP获取本周第一天和最后一天

    //本周的第一天和最后一天  代码如下 复制代码 $date=new DateTime();$date->modify('this week');$first_day_of_week=$date ...

  5. PHP学习笔记 - 进阶篇(10)

    PHP学习笔记 - 进阶篇(10) 异常处理 抛出一个异常 从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被 ...

  6. 谈谈css中的before和after

    css中的伪元素before和after,其实有很多小的妙用. 一.基础用法 w3c中的基础用法:用来给元素的内容前面(对应:before)或者后面(对应:after)插入新内容. <p> ...

  7. HMTL笔记——Iframe

    1.以iframe 引入的银行支付界面 不能够弹出插件,但是用户安装了插件才能够去支付. 2.以Iframe引入的页面在引入的界面中的跳转都只能在当前Iframe中完成,如果想要跳出则需要window ...

  8. javascript笔记——js面试问题

    1:javascript中的变量提升(先使用再声明,js中的函数也存在函数提升) 2:js中的事件捕获和事件冒泡(是两个相反的过程) 3:js中的动画队列(比如animate动画没有在点击的时候阻止正 ...

  9. 跨域访问JSONP CORS

    一.JSONP 常用的Jquery框架支持jsonp方式请求,该方式只支持GET方法,传参大小有限,而且需要后台根据jsonp的请求方式进行封装结果返回. 其中参数jsonp默认为callback,j ...

  10. 一些常用sqlite语句

    1,如果表不存在就新建一个 CComBSTR bstrCreatBat(L”CREATE TABLE IF NOT EXISTS tb_Name (\ rowIdIndex  INTEGER PRIM ...