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!"); } }
我们看一下运行的结果:
从结果来看第一次直接计算结果,第二次从缓存中获取。
以上就是spring实现自定义缓存标签的全部内容,希望对大家的学习有所帮助