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

自从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实现自定义缓存标签的全部内容,希望对大家的学习有所帮助

(0)

相关推荐

  • SpringMVC实现数据绑定及表单标签

    首先理解数据绑定 为什么要使用数据绑定 基于HTTP特性,所有的用户输入的请求参数类型都是String,比如下面表单: 但我们提交后,为了将请求信息映射到模型中,还需要手动进行格式转换,此外还借助了一个中转对象productForm,其字段名称和Product一模一样,只是类型为String. @RequestMapping(value = "/product_save",method = RequestMethod.POST) public String saveProduct(Pr

  • SpringMVC表单标签使用详解

    在使用SpringMVC的时候我们可以使用Spring封装的一系列表单标签,这些标签都可以访问到ModelMap中的内容.下面将对这些标签一一介绍. 在正式介绍SpringMVC的表单标签之前,我们需要先在JSP中声明使用的标签,具体做法是在JSP文件的顶部加入以下指令: <%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %> 1.1.form标签 使用Sprin

  • Spring MVC---数据绑定和表单标签详解

    数据绑定和表单标签 数据绑定 数据绑定是将用户输入绑定到领域模型的一种特性,在Spring MVC的controller和view数据传递中,基于HTTP请求的特性,所有HTTP请求参数的类型均为字符串,如果模型领域需要绑定的类型为double或int,则需要手动进行类型转换,而有了数据绑定后,就不需要手动将HTTP请求中的String类型转换为模型需要的类型了,数据绑定的另一个好处是,当输入验证失败时,会重新生成一个HTML表单,无需重新填写输入字段. 表单标签库 表单标签库中包含了可以用在J

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

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

  • 利用spring的拦截器自定义缓存的实现实例代码

    本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示. Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.本文利用Memcached 的实例和spring的拦截器实现缓存自定义的实现.利用拦截器读取自定义的缓存标签,key值的生成策略. 自定义的Cacheable package com.jeex.sci; @Target(ElementT

  • Java自定义简单标签实例

    下面将以权限的控制为例自定义一个标签:一.标签类型 复制代码 代码如下: <wxt:per uri="${pageContext.request.contextPath }/privilege/list"></wxt:per> 步骤:1.自定义一个类PerssionTag 继承SimpleTagSupport(自定义标签一般都会继承这个类) 复制代码 代码如下: package cn.com.liveuc.privilege.tag;import java.io

  • 如何使用Spring自定义Xml标签

    目录 前言 正文 自定义NameSpaceHandler 自定义schema Parser Decorator 总结 前言 在早期基于Xml配置的Spring Mvc项目中,我们往往会使用<context:component-scan basePackage="">这种自定义标签来扫描我们在basePackae配置里的包名下的类,并且会判断这个类是否要注入到Spring容器中(比如这个类上标记了@Component注解就代表需要被Spring注入),如果需要那么它会帮助我们

  • 基于spring 方法级缓存的多种实现

    方案实施 1. spring和ehcache集成 主要获取ehcache作为操作ehcache的对象. spring.xml中注入ehcacheManager和ehCache对象,ehcacheManager是需要加载ehcache.xml配置信息,创建ehcache.xml中配置不同策略的cache. <!-- ehCache 配置管理器 --> <bean id="ehcacheManager" class="org.springframework.ca

  • MyBatis 添加元数据自定义元素标签的实现代码

    开发背景  现有系统中维护了一套业务表相关列.键的元数据,希望通过读取元数据实现自动封装 SQL 语句.自定义主键策略.实现方案为入侵式修改 MyBatis,增加元素标签meta,支持业务开发中可以在XML映射文件中使用. meta元素设计如下: <!-- meta标签 可根据参数获取到对应的表名 动态生成语句 --> <!ELEMENT meta EMPTY> <!ATTLIST meta test CDATA #IMPLIED type (update|insert|se

  • spring框架cacheAnnotation缓存注释声明解析

    目录 1.基于注释声明缓存 1.1@EnableCaching 1.2@Cacheable 1.2.1默认key生成规则 1.2.2声明自定义key 生成 1.2.3默认的cache resolution 1.2.4同步缓存 1.2.5 缓存的条件 1.2.6可用的Spel 评估上下文 1.基于注释声明缓存 声明缓存,Spring缓存抽象提供了一个java annotation集合. @Cacheable:触发缓存填充. @CacheEvict: 触发缓存删除. @CachePut: 不干扰方法

  • Java 图解Spring启动时的后置处理器工作流程是怎样的

    探究Spring的后置处理器 本次我们主要探究invokeBeanFactoryPostProcessors():后面的代码下次再做解析: 入口代码refresh() AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // ...... applicationContext.refresh(); public void refresh() throws

  • Spring MVC 自定义数据转换器的思路案例详解

    数据转换器是指将客户端 http 请求中的参数转换为业务方法中定义的形参,自定义表示开发者可以自主设计转换模式,HandlerAdapter 已经提供了通用的转换,比如将 String 转成 int,String 转成 double,表单数据的封装等,但是在特殊的业务场景下,HandlerAdapter 无法进行转换,就需要开发者自定义转换器. 我们需要实现 Converter 接口来协助 Spring MVC 完成数据类型的转换,下面通过两个案例来介绍如何自定义数据转换器. 案例一:客户端输入

  • Java使用正则表达式删除所有HTML标签的方法示例

    本文实例讲述了Java使用正则表达式删除所有HTML标签的方法.分享给大家供大家参考,具体如下: package com.xz.cxzy.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; public class HtmlUtil { private static final String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/sc

随机推荐