• 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

  • 相关阅读:
    mysql truncate
    蠕虫复制
    mysql 一对多,多对多
    php实现文件下载
    JetBrains PhpStorm 整个项目中查找一个词语
    vim
    程序员减少代码BUG的7种方法,拒绝编程5分钟,查代码2小时!
    创建你的第一个Composer/Packagist包
    Elasticsearch
    Laravel 实践之路: 数据库迁移与数据填充
  • 原文地址:https://www.cnblogs.com/ctxsdhy/p/6421016.html
Copyright © 2020-2023  润新知