From e48503a7676d136754c5d96bc8146839e3097e9c Mon Sep 17 00:00:00 2001 From: huiquan0509 <1076883793@qq.com> Date: Tue, 24 Mar 2020 17:03:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 55 +++++---- .../com/github/hcsp/annotation/Cache.java | 5 + .../hcsp/annotation/CacheClassDecorator.java | 109 +++++++++++++++++- 3 files changed, 142 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index b0c5e67..21663a3 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,11 @@ 5.6.0 test + + net.bytebuddy + byte-buddy + 1.10.8 + @@ -55,31 +60,31 @@ -Dfile.encoding=UTF-8 - - maven-checkstyle-plugin - 3.1.0 - - ${basedir}/.circleci/checkstyle.xml - true - false - - - - compile - compile - - check - - - - - - com.puppycrawl.tools - checkstyle - 8.29 - - - + + maven-checkstyle-plugin + 3.1.0 + + ${basedir}/.circleci/checkstyle.xml + true + false + + + + compile + compile + + check + + + + + + com.puppycrawl.tools + checkstyle + 8.29 + + + diff --git a/src/main/java/com/github/hcsp/annotation/Cache.java b/src/main/java/com/github/hcsp/annotation/Cache.java index b8651b5..9c5e36a 100644 --- a/src/main/java/com/github/hcsp/annotation/Cache.java +++ b/src/main/java/com/github/hcsp/annotation/Cache.java @@ -1,5 +1,10 @@ package com.github.hcsp.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) public @interface Cache { // 标记缓存的时长(秒),默认60s int cacheSeconds() default 60; diff --git a/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java b/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java index fb5d531..65085f6 100644 --- a/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java +++ b/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java @@ -1,5 +1,16 @@ package com.github.hcsp.annotation; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.implementation.MethodDelegation; +import net.bytebuddy.implementation.bind.annotation.*; +import net.bytebuddy.matcher.ElementMatchers; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; + public class CacheClassDecorator { // 将传入的服务类Class进行增强 // 使得返回一个具有如下功能的Class: @@ -7,8 +18,102 @@ public class CacheClassDecorator { // 这意味着,在短时间内调用同一个服务的同一个@Cache方法两次 // 它实际上只被调用一次,第二次的结果直接从缓存中获取 // 注意,缓存的实现需要是线程安全的 - public static Class decorate(Class klass) { - return klass; + + @SuppressWarnings("unchecked") + public static Class decorate(Class klass) throws IllegalAccessException, InstantiationException { + return (Class) new ByteBuddy() + .subclass(klass) + .method(ElementMatchers.isAnnotatedWith(Cache.class)) + .intercept(MethodDelegation.to(CacheAdvisor.class)) + .make() + .load(klass.getClassLoader()) + .getLoaded(); + } + + private static class CacheKey { + private String method; + private Object object; + private Object[] argument; + + CacheKey(String method, Object object, Object[] argument) { + this.method = method; + this.object = object; + this.argument = argument; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CacheKey cacheKey = (CacheKey) o; + return Objects.equals(method, cacheKey.method) && + Objects.equals(object, cacheKey.object) && + Arrays.equals(argument, cacheKey.argument); + } + + @Override + public int hashCode() { + int result = Objects.hash(method, object); + result = 31 * result + Arrays.hashCode(argument); + return result; + } + } + + private static class CacheValue { + private Object value; + private long time; + + CacheValue(Object value, long time) { + this.value = value; + this.time = time; + } + } + + public static class CacheAdvisor { + private static ConcurrentHashMap cache = new ConcurrentHashMap<>(); + + @RuntimeType + public static Object cache( + //调用父类的方法 + @SuperCall Callable superCall, + //当前正在被调用的方法 + @Origin Method method, + //实体方法的对象 + @This Object object, + //所有的参数 + @AllArguments Object[] arguments) throws Exception { + //获取缓存的结果 + CacheKey cacheKey = new CacheKey(method.getName(), object, arguments); + int cacheSeconds = method.getAnnotation(Cache.class).cacheSeconds(); + final CacheValue obj = cache.get(cacheKey); + + if (obj != null) { + long time = cache.get(cacheKey).time; + if (cacheIsExpired(time, cacheSeconds)) { + //缓存过期 + return putNewValueIntoCache(superCall, cacheKey); + } else { + return obj.value; + } + } else { + return putNewValueIntoCache(superCall, cacheKey); + } + } + + private static boolean cacheIsExpired(long time, long cacheSeconds) { + return ((System.currentTimeMillis() - time) > cacheSeconds * 1000); + } + + private static Object putNewValueIntoCache(@SuperCall Callable superCall, CacheKey cacheKey) throws Exception { + Object realResult = superCall.call(); + CacheValue cacheValue = new CacheValue(realResult, System.currentTimeMillis()); + cache.put(cacheKey, cacheValue); + return realResult; + } } public static void main(String[] args) throws Exception { From 475522981973080476a60c3b5e89b5ba6a66e5b1 Mon Sep 17 00:00:00 2001 From: huiquan0509 <1076883793@qq.com> Date: Tue, 24 Mar 2020 17:08:36 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=BF=98=E5=8E=9F=E4=BA=86xml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pom.xml b/pom.xml index 21663a3..dcc24c1 100644 --- a/pom.xml +++ b/pom.xml @@ -44,11 +44,6 @@ 5.6.0 test - - net.bytebuddy - byte-buddy - 1.10.8 -