From bd8925bf9552734c5012eab1e6fb888eb809082e Mon Sep 17 00:00:00 2001
From: concise <15521608275@163.com>
Date: Sun, 30 Aug 2020 16:13:22 +0800
Subject: [PATCH 1/3] =?UTF-8?q?=E5=9F=BA=E4=BA=8E=E6=B3=A8=E8=A7=A3?=
=?UTF-8?q?=E7=9A=84=E7=BC=93=E5=AD=98=E8=A3=85=E9=A5=B0=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 12 ++
.../com/github/hcsp/annotation/Cache.java | 4 +
.../hcsp/annotation/CacheClassDecorator.java | 114 +++++++++++++++++-
.../github/hcsp/annotation/DataService.java | 2 +-
4 files changed, 130 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index cf436d9..e321ca2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,18 @@
5.6.0
test
+
+
+ net.bytebuddy
+ byte-buddy
+ 1.10.14
+
+
+
+ net.bytebuddy
+ byte-buddy
+ 1.10.14
+
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..bf1c81d 100644
--- a/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java
+++ b/src/main/java/com/github/hcsp/annotation/CacheClassDecorator.java
@@ -1,5 +1,20 @@
package com.github.hcsp.annotation;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.SuperCall;
+import net.bytebuddy.implementation.bind.annotation.This;
+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,10 +22,105 @@ public class CacheClassDecorator {
// 这意味着,在短时间内调用同一个服务的同一个@Cache方法两次
// 它实际上只被调用一次,第二次的结果直接从缓存中获取
// 注意,缓存的实现需要是线程安全的
+ @SuppressWarnings("unchecked")
public static Class decorate(Class klass) {
- return klass;
+ return (Class) new ByteBuddy()
+ // 对带有cache缓存的方法进行增强
+ .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.value = value;
+ this.time = time;
+ }
+ }
+
+
+ public static class CacheAdvisor {
+ // 第一次执行真正的查询,第二次从换从中获取,那就要先写个map来存储第一次的缓存
+ private static ConcurrentHashMap cache = new ConcurrentHashMap<>();
+
+ @RuntimeType
+ public static Object cache(
+ @SuperCall Callable