欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-08 15:02:58
自从spring3.1之后,spring引入了抽象缓存,可以通过在方法上添加@cacheable等标签对方法返回的数据进行缓存。但是它到底是怎么实现的呢,我们通过一个例子来...

自从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!"); 
  } 
 
} 

我们看一下运行的结果:

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

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

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