Ehcache缓存结合Spring AOP实现接口数据缓存

下载安装

JAVA代码块

   首先我们要想好要实现什么样的功能,我们需要拦截service层的增删改查接口然后以不同的动作对缓存进行不同的操作:查询、获取、列表等数据从缓存获取,删除、修改等数据删除已有缓存
  • 只添加缓存和读取缓存

    创建JAVA类MethodPutCacheInterceptor(缓存拦截器)该类只对针对get、load、list、search接口做缓存和读取数据

    public class MethodPutCacheInterceptor {
       private Cache ehCache;

    //通过spring注入方式实例化ehcache
    public void setCache(Cache cache) {
        this.ehCache = cache;
    }
    //构造函数
    public MethodPutCacheInterceptor() {
        super();
    }
     //spring AOP 方法被调用时被拦截
     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        //获取类名
        String targetName = pjp.getTarget().getClass().getName();
        //获取方法名
        String methodName = pjp.getSignature().getName();
        //获取参数
        Object[] atguments = pjp.getArgs();
        Object result;
        //获取cache key值
        String cacheKey = getCacheKey(targetName, methodName, atguments);
        //通过key获取缓存value
        Element element = ehCache.get(cacheKey);
        if (element == null) {
            logger.info("从DB读取数据!");
            //执行连接点里面的方法
            result = pjp.proceed();
            //将连接点方法返回的数据添加到缓存里
            element = new Element(cacheKey, (Serializable) result);
            ehCache.put(element);
        } else {
            logger.info("从缓存读取数据!");
        }
        //最终返回缓存数据
        return element.getObjectValue();
    }
    //spring aop 错误返回
    public void doThrowing(JoinPoint jp, Throwable ex) {
        System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");
        System.out.println(ex.getMessage());
    }

    /**
     * 获得cache key的方法,cache key是Cache中一个Element的唯一识
     * cache key包括 包名+类名+方法名
     * @param targetName 类名
     * @param methodName 方法名
     * @param arguments 参数名
     * @return String
     */
    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 (Object object : arguments) {
                sb.append(".").append(object);
            }

        }
        return sb.toString();
    }
}
  • 创建JAVA类MethodRemoveCacheInterceptor(缓存拦截器)该类只对针对delete、remove、update接口做缓存数据清除
public class MethodRemoveCacheInterceptor{
     private Cache ehCache;

     //通过spring注入方式实例化ehcache
     public void setCache(Cache cache) {
        this.ehCache = cache;
     }
     //构造函数
     public MethodPutCacheInterceptor() {
        super();
     }
   public void doAfter(JoinPoint jp) {
        //获取类名
        String targetName = jp.getTarget().getClass().getName();
        //获取缓存key集合
        List list = ehCache.getKeys();
        for (Object key : list) {
            String cacheKey = String.valueOf(key);
            //判断key中是否含有该类名
            if (cacheKey.startsWith(targetName)) {
                //存在则删除该缓存
                ehCache.remove(cacheKey);
            }
        }
    }
     public void doThrowing(JoinPoint jp, Throwable ex) {
        //获取错误信息
      System.out.println("method " +jp.getTarget().getClass().getName() + "." +      jp.getSignature().getName() + " throw exception");
      System.out.println(ex.getMessage());
    }
}

applicationContext.xml配置

<!--注入EhCacheManagerFactoryBean-->
<bean id="defaultCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <!--获取ehcache.xml文件-->
        <property name="configLocation">        
            <value>classpath:cache/ehcache.xml</value>
        </property>
    </bean>

<!--注入EhCacheFactoryBean-->
    <bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
        <!--指定父类cacheManager的bean-->
        <property name="cacheManager" ref="defaultCacheManager" />
        <!--指定ehcache.xml缓存名为userCache的缓存配置,没找到则默认为defaultCache-->
        <property name="cacheName">
            <value>userCache</value>
        </property>
    </bean>
    <!--将EhCacheFactoryBean注入到类MethodPutCacheInterceptor中cache对象中-->
    <bean id="methodPutCacheInterceptor" class="dome.core.tools.ehcache.MethodPutCacheInterceptor">
        <property name="cache" ref="ehCache" />
    </bean>

    <!--Spring AOP 实现配置-->
    <!--实现service层中get、list、find接口拦截-->
    <aop:config>
        <aop:aspect id="MethodPutCacheInterceptor" ref="methodPutCacheInterceptor">
            <aop:pointcut id="methodPutCacheService"
                expression="execution(* dome.core.*.service.*.get*(..)) or
                            execution(* dome.core.*.service.*.list*(..)) or 
                            execution(* dome.core.*.service.*.find*(..)))"></aop:pointcut>

            <aop:around pointcut-ref="methodPutCacheService" method="doAround" />
            <aop:after-throwing pointcut-ref="methodPutCacheService" method="doThrowing" throwing="ex" />
        </aop:aspect>
    </aop:config>

    <!--实现service层中delete、remove、update接口拦截-->
    <bean id="methodRemoveCacheInterceptor" class="dome.core.tools.ehcache.MethodRemoveCacheInterceptor">
        <property name="cache" ref="ehCache" />
    </bean>

    <aop:config>
        <aop:aspect id="MethodRemoveCacheInterceptor" ref="methodRemoveCacheInterceptor">
            <aop:pointcut id="methodRemoveCacheService"
                expression="execution(* dome.core.*.service.*.delete*(..)) or
                            execution(* dome.core.*.service.*.remove*(..)) or
                            execution(* dome.core.*.service.*.update*(..)))"></aop:pointcut>

            <aop:after pointcut-ref="methodRemoveCacheService" method="doAfter" />
            <aop:after-throwing pointcut-ref="methodRemoveCacheService" method="doThrowing" throwing="ex" />
        </aop:aspect>
    </aop:config>

ehcache.xml配置

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
    monitoring="autodetect" dynamicConfig="true">
    <diskStore path="java.io.tmpdir" />

    <defaultCache 
    maxElementsInMemory="1000" 
    eternal="false"
    timeToIdleSeconds="120" 
    timeToLiveSeconds="120" 
    overflowToDisk="false" />

    <cache name="userCache" 
    maxElementsInMemory="10000" 
    eternal="false"
    overflowToDisk="true" 
    timeToIdleSeconds="300000" 
    timeToLiveSeconds="600000"
    memoryStoreEvictionPolicy="LFU">
    </cache>

</ehcache>

每当程序调用service层接口时,就会判断接口名是否以get、list、find开头,如果是则进入spring aop拦截中判断该方法是否在缓存中,如果存在则直接从缓存获取返回值,如果不存在则直接运行连接点方法(业务类或者dao层)然后将返回值放入缓存并返回缓存中的数据。
如果调用serivce层delete、update、remove开头的接口,则进入拦截器判断是否存在该缓存,如果存在则删除缓存。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值