首页 > 编程 > Java > 正文

Java开发框架spring实现自定义缓存标签

2019-11-26 14:45:23
字体:
来源:转载
供稿:网友

自从spring3.1之后,spring引入了抽象缓存,可以通过在方法上添加@Cacheable等标签对方法返回的数据进行缓存。但是它到底是怎么实现的呢,我们通过一个例子来看一下。首先我们定义一个@MyCacheable

package caching.springaop;  import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.ElementType;  /**  * 使用@MyCacheable注解方法  */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyCacheable{  } 

然后定义处理MyCacheable的切面

package caching.springaop;  import java.util.HashMap; import java.util.Map;  import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut;  /**  * 处理MyCacheable方法的切面  */ @Aspect public class CacheAspect {    private Logger logger = Logger.getLogger(CacheAspect.class);   private Map<String, Object> cache;    public CacheAspect() {     cache = new HashMap<String, Object>();   }    /**    * 所有标注了@Cacheable标签的方法切入点    */   @Pointcut("execution(@MyCacheable * *.*(..))")   @SuppressWarnings("unused")   private void cache() {   }    @Around("cache()")   public Object aroundCachedMethods(ProceedingJoinPoint thisJoinPoint)       throws Throwable {     logger.debug("Execution of Cacheable method catched");     //产生缓存数据的key值,像是这个样子caching.aspectj.Calculator.sum(Integer=1;Integer=2;)     StringBuilder keyBuff = new StringBuilder();     //增加类的名字     keyBuff.append(thisJoinPoint.getTarget().getClass().getName());     //加上方法的名字     keyBuff.append(".").append(thisJoinPoint.getSignature().getName());     keyBuff.append("(");     //循环出cacheable方法的参数     for (final Object arg : thisJoinPoint.getArgs()) {       //增加参数的类型和值       keyBuff.append(arg.getClass().getSimpleName() + "=" + arg + ";");     }     keyBuff.append(")");     String key = keyBuff.toString();     logger.debug("Key = " + key);     Object result = cache.get(key);     if (result == null) {       logger.debug("Result not yet cached. Must be calculated...");       result = thisJoinPoint.proceed();       logger.info("Storing calculated value '" + result + "' to cache");       cache.put(key, result);     } else {       logger.debug("Result '" + result + "' was found in cache");          return result;   }  } 

上述代码展示了如何处理MyCacheable自定义的标签,以及默认情况下产生key值的规则。最后生成的key值大概是这个样子:caching.aspectj.Calculator.sum(Integer=1;Integer=2;)
下边这段代码在方法上添加了MyCacheable标签

package caching.springaop;  import org.apache.log4j.Logger; public class Calculator {   private Logger logger = Logger.getLogger(Calculator.class);   @MyCacheable   public int sum(int a, int b) {     logger.info("Calculating " + a + " + " + b);     try {       //假设这是代价非常高的计算       Thread.sleep(3000);     } catch (InterruptedException e) {       logger.error("Something went wrong...", e);     }     return a + b;   } } 

在方法上加了MyCacheable标签,当key值相同的情况下会直接在缓存中获取数据,如果没有相同的key值,则会重新计算,因为这里只是一个加和操作,耗时非常的短暂。我们在这里让其睡眠3秒钟。
我们在spring-config.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:aop="http://www.springframework.org/schema/aop"   xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">   <aop:aspectj-autoproxy />   <bean class="caching.springaop.CacheAspect" />   <bean id="calc" class="caching.springaop.Calculator" /> </beans> 

测试类:

package caching.springaop;  import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  /**  * 使用SpringAOP缓存的简单例子  * @author txxs  */ public class App {    private static Logger logger = Logger.getLogger(App.class);    public static void main(String[] args) {     logger.debug("Starting...");     ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");     Calculator calc = (Calculator) ctx.getBean("calc");     //计算出来的结果将会被存储在cache     logger.info("1 + 2 = " + calc.sum(1, 2));     //从缓存中获取结果     logger.info("1 + 2 = " + calc.sum(1, 2));     logger.debug("Finished!");   }  } 

我们看一下运行的结果:

从结果来看第一次直接计算结果,第二次从缓存中获取。

以上就是spring实现自定义缓存标签的全部内容,希望对大家的学习有所帮助

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表