Maison  >  Article  >  Java  >  Le cadre de développement Java Spring implémente des balises de cache personnalisées

Le cadre de développement Java Spring implémente des balises de cache personnalisées

高洛峰
高洛峰original
2017-01-23 09:13:251541parcourir

Depuis Spring 3.1, Spring a introduit la mise en cache abstraite, qui peut mettre en cache les données renvoyées par la méthode en ajoutant des balises telles que @Cacheable sur la méthode. Mais comment est-il mis en œuvre ? Prenons un exemple. Nous définissons d’abord un @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{
  
}

puis définissons l’aspect qui gère 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;
  }
  
}

Le code ci-dessus montre comment gérer les balises personnalisées MyCacheable et les règles de génération des valeurs clés par défaut. La valeur de clé générée finale ressemble probablement à ceci : caching.aspectj.Calculator.sum(Integer=1;Integer=2;)
Le code suivant ajoute la balise MyCacheable à la méthode

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;
  }
}

Ajoutez la balise MyCacheable à la méthode. Lorsque les valeurs clés sont les mêmes, les données seront obtenues directement du cache. S'il n'y a pas la même valeur clé, ce sera le cas. sera recalculé, car voici juste Une opération d'addition prend très peu de temps. On le laisse dormir 3 secondes ici.
Nous configurons le spring-config.xml comme suit :

<?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>

Classe de test :

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

Regardons les résultats de l'opération :

Le cadre de développement Java Spring implémente des balises de cache personnalisées

A partir des résultats, la première fois le résultat est calculé directement, et le la deuxième fois, il est obtenu du cache.

Ce qui précède est tout le contenu de l'implémentation par Spring des balises de cache personnalisées. J'espère que cela sera utile à l'apprentissage de chacun

Pour plus d'articles liés à l'implémentation par Spring des balises de cache personnalisées. , veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn