diff --git a/pom.xml b/pom.xml
index b0c5e67..8f14ea8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,6 +44,12 @@
5.6.0
test
+
+ net.bytebuddy
+ byte-buddy
+ 1.10.6
+
+
diff --git a/src/main/java/com/github/hcsp/annotation/Cache.java b/src/main/java/com/github/hcsp/annotation/Cache.java
index b8651b5..63febca 100644
--- a/src/main/java/com/github/hcsp/annotation/Cache.java
+++ b/src/main/java/com/github/hcsp/annotation/Cache.java
@@ -1,5 +1,9 @@
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..1febfbb 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,95 @@ public class CacheClassDecorator {
// 这意味着,在短时间内调用同一个服务的同一个@Cache方法两次
// 它实际上只被调用一次,第二次的结果直接从缓存中获取
// 注意,缓存的实现需要是线程安全的
+ @SuppressWarnings("unchecked")
public static Class decorate(Class klass) {
- return klass;
+ 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 Object thisObject;
+ private String methodName;
+ private Object[] arguments;
+
+ CacheKey(Object thisObject, String methodName, Object[] arguments) {
+ this.thisObject = thisObject;
+ this.methodName = methodName;
+ this.arguments = arguments;
+ }
+
+ @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(thisObject, cacheKey.thisObject) &&
+ Objects.equals(methodName, cacheKey.methodName) &&
+ Arrays.equals(arguments, cacheKey.arguments);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(thisObject, methodName);
+ result = 31 * result + Arrays.hashCode(arguments);
+ return result;
+ }
+ }
+
+ private static class CacheValue {
+ private Object value;
+ private long time;
+
+ CacheValue(Object value, long time) {
+ this.time = time;
+ this.value = value;
+ }
+ }
+
+ public static class CacheAdvisor {
+ private static ConcurrentHashMap cache = new ConcurrentHashMap<>();
+
+ @RuntimeType
+ public static Object cache(
+ @SuperCall Callable