zoukankan      html  css  js  c++  java
  • 转Spring+Hibernate+EHcache配置(二)

    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> 

     

  • 相关阅读:
    好的开源项目汇总
    强制SVN上传代码时添加日志
    微信开发-回调模式
    Struct2中自定义的Filter无效
    Ajax 传包含集合的JSON
    PostgreSQL数据库PL/PGSQL学习使用
    单用户对比PG 9.5.4和SYBASE 15.7对超大表的操作性能
    一场一波三折的SQL优化经历
    聚簇索引对数据插入的影响
    磁盘IO初探
  • 原文地址:https://www.cnblogs.com/sandea/p/3758124.html
Copyright © 2011-2022 走看看