首頁 >Java >java教程 >Java開發框架spring實作自訂快取標籤

Java開發框架spring實作自訂快取標籤

高洛峰
高洛峰原創
2017-01-23 09:13:251555瀏覽

自從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 &#39;" + result + "&#39; to cache");
      cache.put(key, result);
    } else {
      logger.debug("Result &#39;" + result + "&#39; was found in cache");
      
    return result;
  }
  
}

   

非常元的標籤最後產生的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實作自訂快取標籤的全部內容,希望對大家的學習有所幫助Java開發框架spring實作自訂快取標籤

更多Java開發框架spring實作自訂快取標籤相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn