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

时间: 2024-11-20 15:03:29

spring中基于aop使用ehcache的相关文章

Spring中的AOP(五)——在Advice方法中获取目标方法的参数

摘要: 本文介绍使用Spring AOP编程中,在增强处理方法中获取目标方法的参数,定义切点表达式时使用args来快速获取目标方法的参数. 获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Ob

深入分析JavaWeb Item54 -- Spring中的AOP面向切面编程2

一.在Advice方法中获取目标方法的参数 1.获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Object getTarget:返回被织入增强处理的目标对象 Object getThis:返

Spring 框架的概述以及Spring中基于XML的IOC配置

Spring 框架的概述以及Spring中基于XML的IOC配置 一.简介 Spring的两大核心:IOC(DI)与AOP,IOC是反转控制,DI依赖注入 特点:轻量级.依赖注入.面向切面编程.容器.框架.一站式 优势: 方便解耦:做到编译期不依赖,运行期才依赖 AOP的支持 声明式事务的支持 方便程序的测试 方便整合各种框架 降低JavaEE API的使用难度 Spring源码很厉害 解耦: 耦合包括:类之间的和方法之间的 解决的思路: 在创建对象的时候用反射来创建,而不是new 读取配置文件

spring中的aop注解(整合junit测试)

使用spring中的aop前先来了解一下spring中aop中的一些名词 Joimpoint(连接点):目标对象中,所有可能增强的方法 PointCut(切入点):目标对象,已经增强的方法 Advice(通知/增强):增强的代码 Target(目标对象):被代理对象 Weaving(织入):将通知应用到切入点的过程 Proxy(代理):将通知织入到目标对象之后,形成代理对象 aspect(切面):切入点+通知 一:不使用spring的aop注解 以javaEE中的service层为例 UserS

在Spring中基于JDBC进行数据访问时如何控制超时

超时分类 超时根据作用域可做如下层级划分: Transaction Timeout > Statement Timeout > JDBC Driver Socket Timeout Transaction Timeout指一组SQL操作执行时应在设定的时间内完成(提交或回滚),否则将引发超时.它的值应大于 N(语句数) * Statement Timeout Statement Timeout指完成单条SQL语句执行的最大允许时间.它的值应小于JDBC Driver Socket Timeou

Spring中的AOP

在上一篇博客中,我们讲了Spring的IOC,以下,我们继续解说Spring的还有一个核心AOP AOP: 在软件业,AOP为Aspect Oriented Programming的缩写.意为:面向切面编程,通过预编译方式和执行期动态代理实现程序功能的统一维护的一种技术. AOP也是Action Oriented Programming 的缩写,意为:面向切面编程,是函数式编程的一种衍生范型.AOP在其它领域也有其它含义. AOP的具体解释: 还是老规矩,站在巨人的肩膀上,看看其它人对AOP的理

spring中的AOP 以及各种通知

理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦. spring中的AOP很好地解决了这个问题,通过 execution表达式 指定哪些包中的那些类 哪些方法 用到事务 execution(public * *(..))  所有的公共方法 execution(* set*(..))  以set开头的任意方法 execution(* com.xyz.service.AccountSer

Java——面向切面编程,Spring中的AOP编程

面向切面编程 AOP思想:将横向重复代码,纵向抽取出来 AOP体现--Filter AOP体现--拦截器 AOP体现--动态代理 Spring中实现AOP思想 原理:Spring可以为容器中管理的对象生成代理对象 代理分为动态代理和cglib代理: 动态代理(优先) 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术,换句话说,就是代理对象和被代理要实现同一接口 cglib代理 第三方代理技术,cglib代理,可以对任何类生成代理,代理的原理是对目标对象进行继承代理,

2018.12.24 Spring中的aop演示

Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 4.spring中的aop演示 4.1步骤: 1.导包(4+2+2+2+1) 基础包+日志包+aop.aspects+test+weaver+aopalliance 下面两个是spring需要的第三方aop包 com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar com.springsource.or