From afec947e078f1cd70e34052beeb8c39039f95f4f Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 08:49:31 +0800
Subject: [PATCH 01/32] build: add jandex dependency
---
microsphere-redis-parent/pom.xml | 7 +++++++
microsphere-redis-spring/pom.xml | 5 +++++
2 files changed, 12 insertions(+)
diff --git a/microsphere-redis-parent/pom.xml b/microsphere-redis-parent/pom.xml
index 02c34be..e8a862c 100644
--- a/microsphere-redis-parent/pom.xml
+++ b/microsphere-redis-parent/pom.xml
@@ -28,6 +28,7 @@
3.1.6
2021.0.5.0
2021.0.7
+ 3.1.6
@@ -107,6 +108,12 @@
import
+
+
+ io.smallrye
+ jandex
+ ${jandex.version}
+
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index 46e012c..06b5dfa 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -66,6 +66,11 @@
snakeyaml
+
+ io.smallrye
+ jandex
+ true
+
junit
From 8fec691f0985f713b3ec43e2fc3772d27219404c Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 10:22:50 +0800
Subject: [PATCH 02/32] feat: get method info from RedisCommand class
---
.../metadata/RedisCommandsMethodHandles.java | 84 +++++++++++++++++++
.../RedisCommandsMethodHandlesTest.java | 43 ++++++++++
2 files changed, 127 insertions(+)
create mode 100644 microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
create mode 100644 microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
new file mode 100644
index 0000000..436e66c
--- /dev/null
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -0,0 +1,84 @@
+package io.microsphere.redis.spring.metadata;
+
+import org.jboss.jandex.Index;
+import org.jboss.jandex.MethodInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.redis.connection.RedisCommands;
+import org.springframework.data.redis.connection.RedisConnectionCommands;
+import org.springframework.data.redis.connection.RedisGeoCommands;
+import org.springframework.data.redis.connection.RedisHashCommands;
+import org.springframework.data.redis.connection.RedisHyperLogLogCommands;
+import org.springframework.data.redis.connection.RedisKeyCommands;
+import org.springframework.data.redis.connection.RedisListCommands;
+import org.springframework.data.redis.connection.RedisPubSubCommands;
+import org.springframework.data.redis.connection.RedisScriptingCommands;
+import org.springframework.data.redis.connection.RedisServerCommands;
+import org.springframework.data.redis.connection.RedisSetCommands;
+import org.springframework.data.redis.connection.RedisStreamCommands;
+import org.springframework.data.redis.connection.RedisStringCommands;
+import org.springframework.data.redis.connection.RedisTxCommands;
+import org.springframework.data.redis.connection.RedisZSetCommands;
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class RedisCommandsMethodHandles {
+ private static final Logger logger = LoggerFactory.getLogger(RedisCommandsMethodHandles.class);
+ private static List> TARGET_CLASSES;
+
+ /**
+ * get all public methods from {@link RedisCommands}
+ * exclude {@link RedisCommands#execute}
+ * exclude private lambda method from {@link RedisStreamCommands}
+ * lambda$xDel$1
+ * lambda$xAck$0
+ *
+ * @return
+ */
+ static List getAllRedisCommandMethods() {
+ try {
+ Index index = Index.of(TARGET_CLASSES);
+
+ return index.getClassByName(RedisCommands.class)
+ .interfaceNames()
+ .stream()
+ .map(index::getClassByName)
+ .flatMap(classInfo -> classInfo.methods().stream())
+ .filter(methodInfo -> Modifier.isPublic(methodInfo.flags()))
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+
+ logger.error("Can't get RedisCommands Methods", e);
+
+ throw new RuntimeException("Can't get RedisCommands Methods");
+ }
+ }
+ static Map initRedisCommandMethodHandle() {
+ return null;
+ }
+
+ static {
+ TARGET_CLASSES = new ArrayList<>();
+ TARGET_CLASSES.add(RedisCommands.class);
+ TARGET_CLASSES.add(RedisKeyCommands.class);
+ TARGET_CLASSES.add(RedisStringCommands.class);
+ TARGET_CLASSES.add(RedisListCommands.class);
+ TARGET_CLASSES.add(RedisSetCommands.class);
+ TARGET_CLASSES.add(RedisZSetCommands.class);
+ TARGET_CLASSES.add(RedisHashCommands.class);
+ TARGET_CLASSES.add(RedisTxCommands.class);
+ TARGET_CLASSES.add(RedisPubSubCommands.class);
+ TARGET_CLASSES.add(RedisConnectionCommands.class);
+ TARGET_CLASSES.add(RedisServerCommands.class);
+ TARGET_CLASSES.add(RedisStreamCommands.class);
+ TARGET_CLASSES.add(RedisScriptingCommands.class);
+ TARGET_CLASSES.add(RedisGeoCommands.class);
+ TARGET_CLASSES.add(RedisHyperLogLogCommands.class);
+ }
+}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
new file mode 100644
index 0000000..856638c
--- /dev/null
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -0,0 +1,43 @@
+package io.microsphere.redis.spring.metadata;
+
+import org.jboss.jandex.MethodInfo;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.data.redis.connection.RedisCommands;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+
+class RedisCommandsMethodHandlesTest {
+
+ private Class redisCommandClass = RedisCommands.class;
+
+ static int methodCount = RedisCommands.class.getMethods().length - 1;
+
+ @Test
+ void shouldGetAllMethodInfoFromRedisCommand() {
+ List list = getAllRedisCommandMethods();
+
+ assertThat(list)
+ .isNotNull()
+ .hasSize(methodCount);
+ }
+
+ @Disabled
+ @Test
+ void shouldGetMethodHandleFroMethodInfo() {
+ Map map = initRedisCommandMethodHandle();
+ assertThat(map)
+ .isNotNull()
+ .hasSize(methodCount);
+ assertThatNoException().isThrownBy(RedisCommandsMethodHandles::initRedisCommandMethodHandle);
+ }
+}
From 3222193f4caf3abbac9a04dc0b3aa3777c2e82c3 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 10:48:55 +0800
Subject: [PATCH 03/32] build(redis-spring-test): add mockito in test
---
microsphere-redis-spring/pom.xml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index 06b5dfa..afef156 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -103,5 +103,11 @@
test
+
+ org.mockito
+ mockito-inline
+ test
+
+
\ No newline at end of file
From ca4a1f85ee05dc20e0f2c21cadcb879d8f336ad6 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 10:50:38 +0800
Subject: [PATCH 04/32] feat: MethodInfoList to MethodHandleMap
---
.../metadata/RedisCommandsMethodHandles.java | 36 ++++++++++++++++++-
.../RedisCommandsMethodHandlesTest.java | 27 +++++++-------
2 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 436e66c..d4fbe70 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -59,7 +59,41 @@ static List getAllRedisCommandMethods() {
throw new RuntimeException("Can't get RedisCommands Methods");
}
}
- static Map initRedisCommandMethodHandle() {
+
+ static Map initRedisCommandMethodHandle() {
+ List methods = getAllRedisCommandMethods();
+
+ return methods.stream()
+ .map(methodInfo -> {
+ String methodSignature = methodInfo.toString();
+ MethodHandle methodHandle = generateMethodHandle();
+ return new MethodRecord(methodSignature, methodHandle);
+ })
+ .collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
+ }
+
+ /**
+ * Use Record Class when use jdk 17+
+ */
+ static class MethodRecord {
+ String methodSignature;
+ MethodHandle methodHandle;
+
+ public MethodRecord(String methodSignature, MethodHandle methodHandle) {
+ this.methodSignature = methodSignature;
+ this.methodHandle = methodHandle;
+ }
+
+ public String methodSignature() {
+ return methodSignature;
+ }
+
+ public MethodHandle methodHandle() {
+ return methodHandle;
+ }
+ }
+
+ static MethodHandle generateMethodHandle() {
return null;
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 856638c..fd55f8c 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -1,13 +1,11 @@
package io.microsphere.redis.spring.metadata;
import org.jboss.jandex.MethodInfo;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
@@ -15,11 +13,11 @@
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
class RedisCommandsMethodHandlesTest {
- private Class redisCommandClass = RedisCommands.class;
-
static int methodCount = RedisCommands.class.getMethods().length - 1;
@Test
@@ -31,13 +29,18 @@ void shouldGetAllMethodInfoFromRedisCommand() {
.hasSize(methodCount);
}
- @Disabled
@Test
- void shouldGetMethodHandleFroMethodInfo() {
- Map map = initRedisCommandMethodHandle();
- assertThat(map)
- .isNotNull()
- .hasSize(methodCount);
- assertThatNoException().isThrownBy(RedisCommandsMethodHandles::initRedisCommandMethodHandle);
+ void shouldGetMethodHandleMapFromMethodInfo() {
+ try (MockedStatic mockStatic = mockStatic(RedisCommandsMethodHandles.class)) {
+ MethodHandle mockMethodHandle = mock(MethodHandle.class);
+ mockStatic.when(RedisCommandsMethodHandles::getAllRedisCommandMethods).thenCallRealMethod();
+ mockStatic.when(RedisCommandsMethodHandles::initRedisCommandMethodHandle).thenCallRealMethod();
+ mockStatic.when(RedisCommandsMethodHandles::generateMethodHandle).thenReturn(mockMethodHandle);
+
+ Map map = initRedisCommandMethodHandle();
+ assertThat(map)
+ .isNotNull()
+ .hasSize(methodCount);
+ }
}
}
From 85d32568c27da7800b7ab5d6822648bce147878e Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 10:57:19 +0800
Subject: [PATCH 05/32] feat: change generateMethodHandle method Signature
---
.../metadata/RedisCommandsMethodHandles.java | 4 ++--
.../RedisCommandsMethodHandlesTest.java | 18 +++++++++++++++---
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index d4fbe70..051f1e3 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -66,7 +66,7 @@ static Map initRedisCommandMethodHandle() {
return methods.stream()
.map(methodInfo -> {
String methodSignature = methodInfo.toString();
- MethodHandle methodHandle = generateMethodHandle();
+ MethodHandle methodHandle = generateMethodHandle(methodInfo);
return new MethodRecord(methodSignature, methodHandle);
})
.collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
@@ -93,7 +93,7 @@ public MethodHandle methodHandle() {
}
}
- static MethodHandle generateMethodHandle() {
+ static MethodHandle generateMethodHandle(MethodInfo methodInfo) {
return null;
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index fd55f8c..e6a0b69 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -1,6 +1,7 @@
package io.microsphere.redis.spring.metadata;
import org.jboss.jandex.MethodInfo;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
@@ -9,10 +10,11 @@
import java.util.List;
import java.util.Map;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.generateMethodHandle;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
@@ -32,10 +34,11 @@ void shouldGetAllMethodInfoFromRedisCommand() {
@Test
void shouldGetMethodHandleMapFromMethodInfo() {
try (MockedStatic mockStatic = mockStatic(RedisCommandsMethodHandles.class)) {
- MethodHandle mockMethodHandle = mock(MethodHandle.class);
mockStatic.when(RedisCommandsMethodHandles::getAllRedisCommandMethods).thenCallRealMethod();
mockStatic.when(RedisCommandsMethodHandles::initRedisCommandMethodHandle).thenCallRealMethod();
- mockStatic.when(RedisCommandsMethodHandles::generateMethodHandle).thenReturn(mockMethodHandle);
+
+ MethodHandle mockMethodHandle = mock(MethodHandle.class);
+ mockStatic.when(() -> generateMethodHandle(any(MethodInfo.class))).thenReturn(mockMethodHandle);
Map map = initRedisCommandMethodHandle();
assertThat(map)
@@ -43,4 +46,13 @@ void shouldGetMethodHandleMapFromMethodInfo() {
.hasSize(methodCount);
}
}
+
+ @Disabled
+ @Test
+ void shouldNewMethodHandleInstanceByMethodInfo() {
+ MethodInfo methodInfo = mock(MethodInfo.class);
+ MethodHandle methodHandle = generateMethodHandle(methodInfo);
+ assertThat(methodHandle)
+ .isNotNull();
+ }
}
From fd6d8d7eecd0a801503352535010d36d63ddcf4b Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 11:19:08 +0800
Subject: [PATCH 06/32] feat: implement findMethodHande
---
.../metadata/RedisCommandsMethodHandles.java | 70 +++++++++++++------
.../RedisCommandsMethodHandlesTest.java | 26 +++++--
2 files changed, 72 insertions(+), 24 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 051f1e3..353dcb0 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -2,6 +2,7 @@
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
+import org.jboss.jandex.MethodParameterInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisCommands;
@@ -22,14 +23,24 @@
import java.io.IOException;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import static io.microsphere.util.ClassLoaderUtils.*;
+
public class RedisCommandsMethodHandles {
+
private static final Logger logger = LoggerFactory.getLogger(RedisCommandsMethodHandles.class);
+
+ private static final MethodHandles.Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup();
+
+ private static final ClassLoader CURRENT_CLASS_LOADER = RedisCommandsMethodHandles.class.getClassLoader();
+
private static List> TARGET_CLASSES;
/**
@@ -66,35 +77,33 @@ static Map initRedisCommandMethodHandle() {
return methods.stream()
.map(methodInfo -> {
String methodSignature = methodInfo.toString();
- MethodHandle methodHandle = generateMethodHandle(methodInfo);
+ MethodHandle methodHandle = findMethodHandle(methodInfo);
return new MethodRecord(methodSignature, methodHandle);
})
.collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
}
- /**
- * Use Record Class when use jdk 17+
- */
- static class MethodRecord {
- String methodSignature;
- MethodHandle methodHandle;
- public MethodRecord(String methodSignature, MethodHandle methodHandle) {
- this.methodSignature = methodSignature;
- this.methodHandle = methodHandle;
- }
+ static MethodHandle findMethodHandle(MethodInfo methodInfo) {
+ try {
+ Class> klass = loadClass(methodInfo.declaringClass().name().toString(), CURRENT_CLASS_LOADER);
- public String methodSignature() {
- return methodSignature;
- }
+ String methodName = methodInfo.name();
- public MethodHandle methodHandle() {
- return methodHandle;
- }
- }
+ Class> returnTypeKlass = loadClass(methodInfo.returnType().toString(), CURRENT_CLASS_LOADER);
- static MethodHandle generateMethodHandle(MethodInfo methodInfo) {
- return null;
+ MethodParameterInfo[] array = methodInfo.parameters().toArray(new MethodParameterInfo[]{});
+ Class>[] parameterKlass = new Class>[array.length];
+ for (int i = 0; i < array.length; i++) {
+ parameterKlass[i] = loadClass(array[i].type().toString(), CURRENT_CLASS_LOADER);
+ }
+ MethodType methodType = MethodType.methodType(returnTypeKlass, parameterKlass);
+
+ return RedisCommandsMethodHandles.PUBLIC_LOOKUP.findVirtual(klass, methodName, methodType);
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ logger.error("Error occurred when find MethodHandle.\n methodInfo:{}", methodInfo, e);
+ throw new RuntimeException(e);
+ }
}
static {
@@ -115,4 +124,25 @@ static MethodHandle generateMethodHandle(MethodInfo methodInfo) {
TARGET_CLASSES.add(RedisGeoCommands.class);
TARGET_CLASSES.add(RedisHyperLogLogCommands.class);
}
+
+ /**
+ * Use Record Class when use jdk 17+
+ */
+ static class MethodRecord {
+ String methodSignature;
+ MethodHandle methodHandle;
+
+ public MethodRecord(String methodSignature, MethodHandle methodHandle) {
+ this.methodSignature = methodSignature;
+ this.methodHandle = methodHandle;
+ }
+
+ public String methodSignature() {
+ return methodSignature;
+ }
+
+ public MethodHandle methodHandle() {
+ return methodHandle;
+ }
+ }
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index e6a0b69..66c612a 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -1,16 +1,21 @@
package io.microsphere.redis.spring.metadata;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
+import org.springframework.data.redis.connection.RedisStringCommands;
+import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.generateMethodHandle;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.findMethodHandle;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
@@ -38,7 +43,7 @@ void shouldGetMethodHandleMapFromMethodInfo() {
mockStatic.when(RedisCommandsMethodHandles::initRedisCommandMethodHandle).thenCallRealMethod();
MethodHandle mockMethodHandle = mock(MethodHandle.class);
- mockStatic.when(() -> generateMethodHandle(any(MethodInfo.class))).thenReturn(mockMethodHandle);
+ mockStatic.when(() -> findMethodHandle(any(MethodInfo.class))).thenReturn(mockMethodHandle);
Map map = initRedisCommandMethodHandle();
assertThat(map)
@@ -50,9 +55,22 @@ void shouldGetMethodHandleMapFromMethodInfo() {
@Disabled
@Test
void shouldNewMethodHandleInstanceByMethodInfo() {
- MethodInfo methodInfo = mock(MethodInfo.class);
- MethodHandle methodHandle = generateMethodHandle(methodInfo);
+ MethodInfo methodInfo = getMethodInfo();
+
+ MethodHandle methodHandle = findMethodHandle(methodInfo);
assertThat(methodHandle)
.isNotNull();
+
+ }
+
+ private static MethodInfo getMethodInfo() {
+ try {
+ Index index = Index.of(RedisStringCommands.class);
+ ClassInfo classInfo = index.getClassByName(RedisStringCommands.class);
+ Optional setMethod = classInfo.methods().stream().filter(methodInfo -> methodInfo.name().equals("set")).findFirst();
+ return setMethod.get();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
From 16b7b28cc0b2f856d7b92f9143353e247c4f17b4 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 11:58:35 +0800
Subject: [PATCH 07/32] build: add jupiter
---
microsphere-redis-spring/pom.xml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index afef156..03c1d98 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -108,6 +108,9 @@
mockito-inline
test
-
+
+ org.junit.jupiter
+ junit-jupiter
+
\ No newline at end of file
From 6ce07bb6147de528606c286b74546cac937ac066 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 11:59:06 +0800
Subject: [PATCH 08/32] feat: getClassBy Method
add PrimitiveType
---
.../metadata/RedisCommandsMethodHandles.java | 29 ++++++++++++++++
.../RedisCommandsMethodHandlesTest.java | 33 +++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 353dcb0..537dba5 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -3,6 +3,8 @@
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
+import org.jboss.jandex.PrimitiveType;
+import org.jboss.jandex.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisCommands;
@@ -27,6 +29,8 @@
import java.lang.invoke.MethodType;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -106,6 +110,13 @@ static MethodHandle findMethodHandle(MethodInfo methodInfo) {
}
}
+ static Class> getClassBy(Type type) {
+ if (type instanceof PrimitiveType) {
+ return TypeHelper.PRIMITIVE_TYPE_CLASS_TABLE.get(type.asPrimitiveType().primitive());
+ }
+ return null;
+ }
+
static {
TARGET_CLASSES = new ArrayList<>();
TARGET_CLASSES.add(RedisCommands.class);
@@ -145,4 +156,22 @@ public MethodHandle methodHandle() {
return methodHandle;
}
}
+
+ static class TypeHelper {
+ private static final EnumMap> PRIMITIVE_TYPE_CLASS_TABLE;
+
+ static {
+ Map> tmp = new HashMap<>();
+ tmp.put(PrimitiveType.Primitive.BOOLEAN, boolean.class);
+ tmp.put(PrimitiveType.Primitive.BYTE, byte.class);
+ tmp.put(PrimitiveType.Primitive.SHORT, short.class);
+ tmp.put(PrimitiveType.Primitive.INT, int.class);
+ tmp.put(PrimitiveType.Primitive.LONG, long.class);
+ tmp.put(PrimitiveType.Primitive.FLOAT, float.class);
+ tmp.put(PrimitiveType.Primitive.DOUBLE, double.class);
+ tmp.put(PrimitiveType.Primitive.CHAR, char.class);
+ PRIMITIVE_TYPE_CLASS_TABLE = new EnumMap<>(tmp);
+ }
+
+ }
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 66c612a..95f0de8 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -3,8 +3,13 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
+import org.jboss.jandex.PrimitiveType;
import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.connection.RedisStringCommands;
@@ -14,11 +19,15 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Stream;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.findMethodHandle;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Named.named;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
@@ -60,6 +69,30 @@ void shouldNewMethodHandleInstanceByMethodInfo() {
MethodHandle methodHandle = findMethodHandle(methodInfo);
assertThat(methodHandle)
.isNotNull();
+ }
+
+ @ParameterizedTest(name = "test: {0}")
+ @MethodSource
+ void shouldLoadPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
+ Class> klass = getClassBy(primitiveType.asPrimitiveType());
+ assertThat(klass).isEqualTo(expected);
+ }
+
+ static Stream shouldLoadPrimitiveClass() {
+ return Stream.of(
+ arguments(named("boolean", PrimitiveType.BOOLEAN), boolean.class),
+ arguments(named("byte", PrimitiveType.BYTE), byte.class),
+ arguments(named("short", PrimitiveType.SHORT), short.class),
+ arguments(named("int", PrimitiveType.INT), int.class),
+ arguments(named("long", PrimitiveType.LONG), long.class),
+ arguments(named("float", PrimitiveType.FLOAT), float.class),
+ arguments(named("double", PrimitiveType.DOUBLE), double.class),
+ arguments(named("char", PrimitiveType.CHAR), char.class)
+ );
+ }
+
+ @Test
+ void shouldLoadArrayClass() {
}
From 07c3f4c9a5b5976208b273fb83934eeb8412dd37 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 12:40:56 +0800
Subject: [PATCH 09/32] feat: complete getClassBy Method
add ArrayType
add VoidType
---
.../metadata/RedisCommandsMethodHandles.java | 65 +++++++++++++++----
.../RedisCommandsMethodHandlesTest.java | 35 +++++++++-
2 files changed, 85 insertions(+), 15 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 537dba5..9778460 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -1,10 +1,13 @@
package io.microsphere.redis.spring.metadata;
+import org.apache.commons.lang3.StringUtils;
+import org.jboss.jandex.ArrayType;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.PrimitiveType;
import org.jboss.jandex.Type;
+import org.jboss.jandex.VoidType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisCommands;
@@ -22,6 +25,8 @@
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.RedisTxCommands;
import org.springframework.data.redis.connection.RedisZSetCommands;
+import org.springframework.data.redis.connection.stream.RecordId;
+import org.springframework.data.redis.connection.stream.StreamOffset;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
@@ -33,6 +38,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.stream.Collectors;
import static io.microsphere.util.ClassLoaderUtils.*;
@@ -111,9 +118,36 @@ static MethodHandle findMethodHandle(MethodInfo methodInfo) {
}
static Class> getClassBy(Type type) {
+ if (type instanceof VoidType) {
+ return void.class;
+ }
+
if (type instanceof PrimitiveType) {
return TypeHelper.PRIMITIVE_TYPE_CLASS_TABLE.get(type.asPrimitiveType().primitive());
}
+
+ if (type instanceof ArrayType) {
+ ArrayType arrayType = type.asArrayType();
+ // NOTE: arrayType.elementType().name()
+ // example java.lang.String
+ // when use jdk21 local() value is "String" prefix is "java.lang"
+ // when use jdk8 local() value is "java.lang.String" prefix is null
+ String local = arrayType.elementType().name().local();
+ String elementType;
+ if (local.lastIndexOf(".") != -1) {
+ elementType = local.substring(local.lastIndexOf(".") + 1);
+ } else {
+ elementType = local;
+ }
+ // NOTE: use String.repeat() when use jdk11+ and remove Apache commons lang3 StringUtils dependency
+ String repeat = StringUtils.repeat("[]", arrayType.dimensions());
+ Class> klass = TypeHelper.ARRAY_TYPE_CLASS_TABLE.get(elementType + repeat);
+
+ if (Objects.isNull(klass)) {
+ throw new RuntimeException("need to add Class");
+ }
+ return klass;
+ }
return null;
}
@@ -137,7 +171,7 @@ static Class> getClassBy(Type type) {
}
/**
- * Use Record Class when use jdk 17+
+ * NOTE: Use Record Class when use jdk 17+
*/
static class MethodRecord {
String methodSignature;
@@ -158,19 +192,26 @@ public MethodHandle methodHandle() {
}
static class TypeHelper {
- private static final EnumMap> PRIMITIVE_TYPE_CLASS_TABLE;
+ private static final EnumMap> PRIMITIVE_TYPE_CLASS_TABLE = new EnumMap<>(PrimitiveType.Primitive.class);
+ private static final Map> ARRAY_TYPE_CLASS_TABLE = new HashMap<>();
static {
- Map> tmp = new HashMap<>();
- tmp.put(PrimitiveType.Primitive.BOOLEAN, boolean.class);
- tmp.put(PrimitiveType.Primitive.BYTE, byte.class);
- tmp.put(PrimitiveType.Primitive.SHORT, short.class);
- tmp.put(PrimitiveType.Primitive.INT, int.class);
- tmp.put(PrimitiveType.Primitive.LONG, long.class);
- tmp.put(PrimitiveType.Primitive.FLOAT, float.class);
- tmp.put(PrimitiveType.Primitive.DOUBLE, double.class);
- tmp.put(PrimitiveType.Primitive.CHAR, char.class);
- PRIMITIVE_TYPE_CLASS_TABLE = new EnumMap<>(tmp);
+ // NOTE: use new EnumMap(Map.of()) when use jdk11+
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.BOOLEAN, boolean.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.BYTE, byte.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.SHORT, short.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.INT, int.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.LONG, long.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.FLOAT, float.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.DOUBLE, double.class);
+ PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.CHAR, char.class);
+
+ ARRAY_TYPE_CLASS_TABLE.put("byte[]", byte[].class);
+ ARRAY_TYPE_CLASS_TABLE.put("byte[][]", byte[][].class);
+ ARRAY_TYPE_CLASS_TABLE.put("int[]", int[].class);
+ ARRAY_TYPE_CLASS_TABLE.put("String[]", String[].class);
+ ARRAY_TYPE_CLASS_TABLE.put("RecordId[]", RecordId[].class);
+ ARRAY_TYPE_CLASS_TABLE.put("StreamOffset[]", StreamOffset[].class);
}
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 95f0de8..c992a2f 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -1,9 +1,13 @@
package io.microsphere.redis.spring.metadata;
+import org.jboss.jandex.ArrayType;
import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.PrimitiveType;
+import org.jboss.jandex.Type;
+import org.jboss.jandex.VoidType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
@@ -13,6 +17,8 @@
import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.connection.RedisStringCommands;
+import org.springframework.data.redis.connection.stream.RecordId;
+import org.springframework.data.redis.connection.stream.StreamOffset;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
@@ -26,6 +32,10 @@
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.jboss.jandex.ArrayType.builder;
+import static org.jboss.jandex.DotName.createSimple;
+import static org.jboss.jandex.Type.Kind.CLASS;
+import static org.jboss.jandex.Type.create;
import static org.junit.jupiter.api.Named.named;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.any;
@@ -74,7 +84,7 @@ void shouldNewMethodHandleInstanceByMethodInfo() {
@ParameterizedTest(name = "test: {0}")
@MethodSource
void shouldLoadPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
- Class> klass = getClassBy(primitiveType.asPrimitiveType());
+ Class> klass = getClassBy(primitiveType);
assertThat(klass).isEqualTo(expected);
}
@@ -91,9 +101,28 @@ static Stream shouldLoadPrimitiveClass() {
);
}
- @Test
- void shouldLoadArrayClass() {
+ @ParameterizedTest(name = "test: {0}")
+ @MethodSource
+ void shouldLoadArrayClass(ArrayType arrayType, Class> expected) {
+ Class> klass = getClassBy(arrayType);
+ assertThat(klass).isEqualTo(expected);
+ }
+ static Stream shouldLoadArrayClass() {
+ return Stream.of(
+ arguments(named("byte[]", builder(PrimitiveType.BYTE, 1).build()), byte[].class),
+ arguments(named("byte[][]", builder(PrimitiveType.BYTE, 2).build()), byte[][].class),
+ arguments(named("int[]", builder(PrimitiveType.INT, 1).build()), int[].class),
+ arguments(named("String[]", builder(create(createSimple(String.class), CLASS), 1).build()), String[].class),
+ arguments(named("RecordId[]", builder(create(createSimple(RecordId.class), CLASS), 1).build()), RecordId[].class),
+ arguments(named("StreamOffset[]", builder(create(createSimple(StreamOffset.class), CLASS), 1).build()), StreamOffset[].class)
+ );
+ }
+
+ @Test
+ void shouldVoidClass() {
+ Class> klass = getClassBy(VoidType.VOID);
+ assertThat(klass).isEqualTo(void.class);
}
private static MethodInfo getMethodInfo() {
From 16ad659a4771dbda712cabca2754b038871bd0ea Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 12:44:29 +0800
Subject: [PATCH 10/32] doc: modify comment
---
.../redis/spring/metadata/RedisCommandsMethodHandles.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 9778460..ebd6ac7 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -130,8 +130,8 @@ static Class> getClassBy(Type type) {
ArrayType arrayType = type.asArrayType();
// NOTE: arrayType.elementType().name()
// example java.lang.String
- // when use jdk21 local() value is "String" prefix is "java.lang"
- // when use jdk8 local() value is "java.lang.String" prefix is null
+ // when use jdk21 local() value is "String" prefix() is "java.lang"
+ // when use jdk8 local() value is "java.lang.String" prefix() is null
String local = arrayType.elementType().name().local();
String elementType;
if (local.lastIndexOf(".") != -1) {
@@ -196,7 +196,7 @@ static class TypeHelper {
private static final Map> ARRAY_TYPE_CLASS_TABLE = new HashMap<>();
static {
- // NOTE: use new EnumMap(Map.of()) when use jdk11+
+ // NOTE: use new EnumMap(Map.of()) to simplify the code when use jdk11+
PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.BOOLEAN, boolean.class);
PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.BYTE, byte.class);
PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.SHORT, short.class);
From 52891e559e6044bc42d94a1e7a749cc7860db91e Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 13:18:31 +0800
Subject: [PATCH 11/32] feat: complete getClassBy Method
add ParameterizedType
add ClassType
---
.../metadata/RedisCommandsMethodHandles.java | 7 +++--
.../RedisCommandsMethodHandlesTest.java | 29 ++++++++++++++-----
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index ebd6ac7..62037e9 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -1,5 +1,6 @@
package io.microsphere.redis.spring.metadata;
+import io.microsphere.util.ClassLoaderUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.jandex.ArrayType;
import org.jboss.jandex.Index;
@@ -39,10 +40,9 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.stream.Collectors;
-import static io.microsphere.util.ClassLoaderUtils.*;
+import static io.microsphere.util.ClassLoaderUtils.loadClass;
public class RedisCommandsMethodHandles {
@@ -148,7 +148,8 @@ static Class> getClassBy(Type type) {
}
return klass;
}
- return null;
+
+ return ClassLoaderUtils.loadClass(type.name().toString(), CURRENT_CLASS_LOADER);
}
static {
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index c992a2f..6662c13 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -2,14 +2,13 @@
import org.jboss.jandex.ArrayType;
import org.jboss.jandex.ClassInfo;
-import org.jboss.jandex.DotName;
+import org.jboss.jandex.ClassType;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
+import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.PrimitiveType;
-import org.jboss.jandex.Type;
import org.jboss.jandex.VoidType;
import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -83,12 +82,12 @@ void shouldNewMethodHandleInstanceByMethodInfo() {
@ParameterizedTest(name = "test: {0}")
@MethodSource
- void shouldLoadPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
+ void shouldGetClassWhenTypeIsPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
Class> klass = getClassBy(primitiveType);
assertThat(klass).isEqualTo(expected);
}
- static Stream shouldLoadPrimitiveClass() {
+ static Stream shouldGetClassWhenTypeIsPrimitiveClass() {
return Stream.of(
arguments(named("boolean", PrimitiveType.BOOLEAN), boolean.class),
arguments(named("byte", PrimitiveType.BYTE), byte.class),
@@ -103,12 +102,12 @@ static Stream shouldLoadPrimitiveClass() {
@ParameterizedTest(name = "test: {0}")
@MethodSource
- void shouldLoadArrayClass(ArrayType arrayType, Class> expected) {
+ void shouldGetClassWhenTypeIsArrayClass(ArrayType arrayType, Class> expected) {
Class> klass = getClassBy(arrayType);
assertThat(klass).isEqualTo(expected);
}
- static Stream shouldLoadArrayClass() {
+ static Stream shouldGetClassWhenTypeIsArrayClass() {
return Stream.of(
arguments(named("byte[]", builder(PrimitiveType.BYTE, 1).build()), byte[].class),
arguments(named("byte[][]", builder(PrimitiveType.BYTE, 2).build()), byte[][].class),
@@ -120,11 +119,25 @@ static Stream shouldLoadArrayClass() {
}
@Test
- void shouldVoidClass() {
+ void shouldGetVoidClass() {
Class> klass = getClassBy(VoidType.VOID);
assertThat(klass).isEqualTo(void.class);
}
+ @Test
+ void shouldGetClassWhenTypeIsParameterizedType() {
+ ParameterizedType parameterizedType = ParameterizedType.builder(List.class).addArgument(ClassType.create(String.class)).build();
+ Class> klass = getClassBy(parameterizedType);
+ assertThat(klass).isEqualTo(List.class);
+ }
+
+ @Test
+ void shouldGetClassWhenTypeIsClassType() {
+ ClassType classType = ClassType.create(Object.class);
+ Class> klass = getClassBy(classType);
+ assertThat(klass).isEqualTo(Object.class);
+ }
+
private static MethodInfo getMethodInfo() {
try {
Index index = Index.of(RedisStringCommands.class);
From 76929c709e3da786b9a5efa07e60a7868855fd7a Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 13:34:56 +0800
Subject: [PATCH 12/32] feat: complete findMethodHandle
---
.../redis/spring/metadata/RedisCommandsMethodHandles.java | 7 ++++---
.../spring/metadata/RedisCommandsMethodHandlesTest.java | 1 -
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 62037e9..00525ea 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -3,6 +3,7 @@
import io.microsphere.util.ClassLoaderUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.jandex.ArrayType;
+import org.jboss.jandex.ClassType;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
@@ -97,16 +98,16 @@ static Map initRedisCommandMethodHandle() {
static MethodHandle findMethodHandle(MethodInfo methodInfo) {
try {
- Class> klass = loadClass(methodInfo.declaringClass().name().toString(), CURRENT_CLASS_LOADER);
+ Class> klass = getClassBy(ClassType.create(methodInfo.declaringClass().name()));
String methodName = methodInfo.name();
- Class> returnTypeKlass = loadClass(methodInfo.returnType().toString(), CURRENT_CLASS_LOADER);
+ Class> returnTypeKlass = getClassBy(methodInfo.returnType());
MethodParameterInfo[] array = methodInfo.parameters().toArray(new MethodParameterInfo[]{});
Class>[] parameterKlass = new Class>[array.length];
for (int i = 0; i < array.length; i++) {
- parameterKlass[i] = loadClass(array[i].type().toString(), CURRENT_CLASS_LOADER);
+ parameterKlass[i] = getClassBy(array[i].type());
}
MethodType methodType = MethodType.methodType(returnTypeKlass, parameterKlass);
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 6662c13..9a9b88a 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -70,7 +70,6 @@ void shouldGetMethodHandleMapFromMethodInfo() {
}
}
- @Disabled
@Test
void shouldNewMethodHandleInstanceByMethodInfo() {
MethodInfo methodInfo = getMethodInfo();
From 89b81ed13ad20f7fe262c9490f0b5d975c9a7b02 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 13:42:55 +0800
Subject: [PATCH 13/32] refactor: simplify the code
---
.../metadata/RedisCommandsMethodHandles.java | 44 ++++++++++---------
.../RedisCommandsMethodHandlesTest.java | 7 ++-
2 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 00525ea..4db4cc4 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -84,33 +84,21 @@ static List getAllRedisCommandMethods() {
}
static Map initRedisCommandMethodHandle() {
- List methods = getAllRedisCommandMethods();
-
- return methods.stream()
- .map(methodInfo -> {
- String methodSignature = methodInfo.toString();
- MethodHandle methodHandle = findMethodHandle(methodInfo);
- return new MethodRecord(methodSignature, methodHandle);
- })
+
+ return getAllRedisCommandMethods()
+ .stream()
+ .map(methodInfo -> new MethodRecord(methodInfo.toString(), findMethodHandle(methodInfo)))
.collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
}
static MethodHandle findMethodHandle(MethodInfo methodInfo) {
- try {
- Class> klass = getClassBy(ClassType.create(methodInfo.declaringClass().name()));
+ Class> klass = getClassBy(ClassType.create(methodInfo.declaringClass().name()));
- String methodName = methodInfo.name();
-
- Class> returnTypeKlass = getClassBy(methodInfo.returnType());
-
- MethodParameterInfo[] array = methodInfo.parameters().toArray(new MethodParameterInfo[]{});
- Class>[] parameterKlass = new Class>[array.length];
- for (int i = 0; i < array.length; i++) {
- parameterKlass[i] = getClassBy(array[i].type());
- }
- MethodType methodType = MethodType.methodType(returnTypeKlass, parameterKlass);
+ String methodName = methodInfo.name();
+ MethodType methodType = getMethodType(methodInfo);
+ try {
return RedisCommandsMethodHandles.PUBLIC_LOOKUP.findVirtual(klass, methodName, methodType);
} catch (NoSuchMethodException | IllegalAccessException e) {
logger.error("Error occurred when find MethodHandle.\n methodInfo:{}", methodInfo, e);
@@ -118,6 +106,19 @@ static MethodHandle findMethodHandle(MethodInfo methodInfo) {
}
}
+ private static MethodType getMethodType(MethodInfo methodInfo) {
+ Class> returnTypeKlass = getClassBy(methodInfo.returnType());
+
+ MethodParameterInfo[] array = methodInfo.parameters().toArray(new MethodParameterInfo[]{});
+ Class>[] parameterKlass = new Class>[array.length];
+ for (int i = 0; i < array.length; i++) {
+ parameterKlass[i] = getClassBy(array[i].type());
+ }
+
+ MethodType methodType = MethodType.methodType(returnTypeKlass, parameterKlass);
+ return methodType;
+ }
+
static Class> getClassBy(Type type) {
if (type instanceof VoidType) {
return void.class;
@@ -197,6 +198,9 @@ static class TypeHelper {
private static final EnumMap> PRIMITIVE_TYPE_CLASS_TABLE = new EnumMap<>(PrimitiveType.Primitive.class);
private static final Map> ARRAY_TYPE_CLASS_TABLE = new HashMap<>();
+ private TypeHelper() {
+ }
+
static {
// NOTE: use new EnumMap(Map.of()) to simplify the code when use jdk11+
PRIMITIVE_TYPE_CLASS_TABLE.put(PrimitiveType.Primitive.BOOLEAN, boolean.class);
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 9a9b88a..d897d94 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -56,6 +56,7 @@ void shouldGetAllMethodInfoFromRedisCommand() {
@Test
void shouldGetMethodHandleMapFromMethodInfo() {
+ /*
try (MockedStatic mockStatic = mockStatic(RedisCommandsMethodHandles.class)) {
mockStatic.when(RedisCommandsMethodHandles::getAllRedisCommandMethods).thenCallRealMethod();
mockStatic.when(RedisCommandsMethodHandles::initRedisCommandMethodHandle).thenCallRealMethod();
@@ -67,7 +68,11 @@ void shouldGetMethodHandleMapFromMethodInfo() {
assertThat(map)
.isNotNull()
.hasSize(methodCount);
- }
+ }*/
+ Map map = initRedisCommandMethodHandle();
+ assertThat(map)
+ .isNotNull()
+ .hasSize(methodCount);
}
@Test
From c8fa4e02f2a05900d0c49e6c4031531b57ce5332 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 14:18:37 +0800
Subject: [PATCH 14/32] feat: find MethodHandle From Map
add method getMethodHandleBy
add MethodHandleNotFoundException when not found
---
.../metadata/RedisCommandsMethodHandles.java | 34 +++++++++++----
.../MethodHandleNotFoundException.java | 14 +++++++
.../RedisCommandsMethodHandlesTest.java | 41 +++++++++++--------
3 files changed, 64 insertions(+), 25 deletions(-)
create mode 100644 microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 4db4cc4..9908121 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -1,5 +1,6 @@
package io.microsphere.redis.spring.metadata;
+import io.microsphere.redis.spring.metadata.exception.MethodHandleNotFoundException;
import io.microsphere.util.ClassLoaderUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.jandex.ArrayType;
@@ -43,8 +44,6 @@
import java.util.Objects;
import java.util.stream.Collectors;
-import static io.microsphere.util.ClassLoaderUtils.loadClass;
-
public class RedisCommandsMethodHandles {
private static final Logger logger = LoggerFactory.getLogger(RedisCommandsMethodHandles.class);
@@ -53,7 +52,27 @@ public class RedisCommandsMethodHandles {
private static final ClassLoader CURRENT_CLASS_LOADER = RedisCommandsMethodHandles.class.getClassLoader();
- private static List> TARGET_CLASSES;
+ private static final List> TARGET_CLASSES;
+ private static final Map METHOD_HANDLE_MAP;
+
+ private RedisCommandsMethodHandles() {
+ }
+
+ /**
+ * find MethodHandle from METHOD_HANDLE_MAP
+ *
+ * @param methodSignature {@link MethodInfo#toString()}
+ * @return a MethodHandle
+ * @throws MethodHandleNotFoundException
+ */
+ public static MethodHandle getMethodHandleBy(String methodSignature) throws MethodHandleNotFoundException {
+ MethodHandle methodHandle = METHOD_HANDLE_MAP.get(methodSignature);
+ if (Objects.isNull(methodHandle)) {
+ logger.error("can't find MethodHandle from RedisCommands methodSignature:{}", methodSignature);
+ throw new MethodHandleNotFoundException("can't find MethodHandle from RedisCommands", methodSignature);
+ }
+ return methodHandle;
+ }
/**
* get all public methods from {@link RedisCommands}
@@ -62,7 +81,7 @@ public class RedisCommandsMethodHandles {
* lambda$xDel$1
* lambda$xAck$0
*
- * @return
+ * @return List of RedisCommands all MethodInfo(include super interface)
*/
static List getAllRedisCommandMethods() {
try {
@@ -91,7 +110,6 @@ static Map initRedisCommandMethodHandle() {
.collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
}
-
static MethodHandle findMethodHandle(MethodInfo methodInfo) {
Class> klass = getClassBy(ClassType.create(methodInfo.declaringClass().name()));
@@ -115,8 +133,7 @@ private static MethodType getMethodType(MethodInfo methodInfo) {
parameterKlass[i] = getClassBy(array[i].type());
}
- MethodType methodType = MethodType.methodType(returnTypeKlass, parameterKlass);
- return methodType;
+ return MethodType.methodType(returnTypeKlass, parameterKlass);
}
static Class> getClassBy(Type type) {
@@ -155,6 +172,7 @@ static Class> getClassBy(Type type) {
}
static {
+ // NOTE: use List.of() to simplify the initial logic
TARGET_CLASSES = new ArrayList<>();
TARGET_CLASSES.add(RedisCommands.class);
TARGET_CLASSES.add(RedisKeyCommands.class);
@@ -171,6 +189,8 @@ static Class> getClassBy(Type type) {
TARGET_CLASSES.add(RedisScriptingCommands.class);
TARGET_CLASSES.add(RedisGeoCommands.class);
TARGET_CLASSES.add(RedisHyperLogLogCommands.class);
+
+ METHOD_HANDLE_MAP = initRedisCommandMethodHandle();
}
/**
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
new file mode 100644
index 0000000..b1b2655
--- /dev/null
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
@@ -0,0 +1,14 @@
+package io.microsphere.redis.spring.metadata.exception;
+
+public class MethodHandleNotFoundException extends RuntimeException {
+
+ private final String methodSignature;
+ public MethodHandleNotFoundException(String message, String methodSignature) {
+ super(message);
+ this.methodSignature = methodSignature;
+ }
+
+ public String getMethodSignature() {
+ return methodSignature;
+ }
+}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index d897d94..093f791 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -1,5 +1,6 @@
package io.microsphere.redis.spring.metadata;
+import io.microsphere.redis.spring.metadata.exception.MethodHandleNotFoundException;
import org.jboss.jandex.ArrayType;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.ClassType;
@@ -8,12 +9,10 @@
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.PrimitiveType;
import org.jboss.jandex.VoidType;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
-import org.mockito.MockedStatic;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.stream.RecordId;
@@ -29,17 +28,16 @@
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.findMethodHandle;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.jboss.jandex.ArrayType.builder;
import static org.jboss.jandex.DotName.createSimple;
import static org.jboss.jandex.Type.Kind.CLASS;
import static org.jboss.jandex.Type.create;
import static org.junit.jupiter.api.Named.named;
import static org.junit.jupiter.params.provider.Arguments.arguments;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockStatic;
class RedisCommandsMethodHandlesTest {
@@ -56,19 +54,6 @@ void shouldGetAllMethodInfoFromRedisCommand() {
@Test
void shouldGetMethodHandleMapFromMethodInfo() {
- /*
- try (MockedStatic mockStatic = mockStatic(RedisCommandsMethodHandles.class)) {
- mockStatic.when(RedisCommandsMethodHandles::getAllRedisCommandMethods).thenCallRealMethod();
- mockStatic.when(RedisCommandsMethodHandles::initRedisCommandMethodHandle).thenCallRealMethod();
-
- MethodHandle mockMethodHandle = mock(MethodHandle.class);
- mockStatic.when(() -> findMethodHandle(any(MethodInfo.class))).thenReturn(mockMethodHandle);
-
- Map map = initRedisCommandMethodHandle();
- assertThat(map)
- .isNotNull()
- .hasSize(methodCount);
- }*/
Map map = initRedisCommandMethodHandle();
assertThat(map)
.isNotNull()
@@ -84,6 +69,26 @@ void shouldNewMethodHandleInstanceByMethodInfo() {
.isNotNull();
}
+ @Test
+ void shouldGetMethodHandleByMethodSignature() {
+ String methodSignature = getMethodInfo().toString();
+ MethodHandle methodHandle = getMethodHandleBy(methodSignature);
+ assertThat(methodHandle)
+ .isNotNull();
+ }
+
+ @Test
+ void shouldThrowMethodHandleNotFoundExceptionWhenMiss() {
+ MethodHandleNotFoundException missingMethodSignature = catchThrowableOfType(
+ () -> getMethodHandleBy("MissingMethodSignature"),
+ MethodHandleNotFoundException.class);
+
+ assertThat(missingMethodSignature)
+ .hasMessage("can't find MethodHandle from RedisCommands");
+ assertThat(missingMethodSignature.getMethodSignature())
+ .isEqualTo("MissingMethodSignature");
+ }
+
@ParameterizedTest(name = "test: {0}")
@MethodSource
void shouldGetClassWhenTypeIsPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
From b9ad5bf5b39a23319f05aa5dcdf98cafd5ccab4e Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 15:34:03 +0800
Subject: [PATCH 15/32] build: add testcontainers Dependency
add testcontainers in the test scope
add spring-boot-starter-data-redis in the test scope to autoconfigure in test
---
microsphere-redis-parent/pom.xml | 10 ++++++++++
microsphere-redis-replicator-spring/pom.xml | 16 ++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/microsphere-redis-parent/pom.xml b/microsphere-redis-parent/pom.xml
index e8a862c..350ea65 100644
--- a/microsphere-redis-parent/pom.xml
+++ b/microsphere-redis-parent/pom.xml
@@ -29,6 +29,7 @@
2021.0.5.0
2021.0.7
3.1.6
+ 1.19.5
@@ -114,6 +115,15 @@
jandex
${jandex.version}
+
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
diff --git a/microsphere-redis-replicator-spring/pom.xml b/microsphere-redis-replicator-spring/pom.xml
index 6e12a2d..08d6ab7 100644
--- a/microsphere-redis-replicator-spring/pom.xml
+++ b/microsphere-redis-replicator-spring/pom.xml
@@ -92,6 +92,22 @@
test
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ test
+
+
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
\ No newline at end of file
From 1f940eea82da0d891499c9654262ec421ef54699 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 16:54:26 +0800
Subject: [PATCH 16/32] feat: exception message show methodSignature
---
.../metadata/exception/MethodHandleNotFoundException.java | 4 +++-
.../redis/spring/metadata/RedisCommandsMethodHandlesTest.java | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
index b1b2655..0fae483 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/exception/MethodHandleNotFoundException.java
@@ -3,12 +3,14 @@
public class MethodHandleNotFoundException extends RuntimeException {
private final String methodSignature;
+
public MethodHandleNotFoundException(String message, String methodSignature) {
- super(message);
+ super(message + ", methodSignature is " + methodSignature);
this.methodSignature = methodSignature;
}
public String getMethodSignature() {
return methodSignature;
}
+
}
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 093f791..8a2144d 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -84,7 +84,8 @@ void shouldThrowMethodHandleNotFoundExceptionWhenMiss() {
MethodHandleNotFoundException.class);
assertThat(missingMethodSignature)
- .hasMessage("can't find MethodHandle from RedisCommands");
+ .hasMessageContaining("can't find MethodHandle from RedisCommands")
+ .hasMessageContaining("methodSignature");
assertThat(missingMethodSignature.getMethodSignature())
.isEqualTo("MissingMethodSignature");
}
From ec8205b43ea9300961ad2bdb4e49aebdfb9fb899 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 16:59:55 +0800
Subject: [PATCH 17/32] build: transfer jandex to dependent model
---
microsphere-redis-spring/pom.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index 03c1d98..299b2bb 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -69,7 +69,6 @@
io.smallrye
jandex
- true
From 563db9bc46cb26e62177490913be3e29502de727 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 17:02:00 +0800
Subject: [PATCH 18/32] test: write event handle test case
---
...HandleRedisCommandReplicatedEventTest.java | 109 ++++++++++++++++++
1 file changed, 109 insertions(+)
create mode 100644 microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
new file mode 100644
index 0000000..552455c
--- /dev/null
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -0,0 +1,109 @@
+package io.microsphere.redis.replicator.spring;
+
+import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
+import io.microsphere.redis.spring.event.RedisCommandEvent;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import java.lang.reflect.Method;
+
+import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
+import static io.microsphere.redis.spring.serializer.RedisCommandEventSerializer.VERSION_V1;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.testcontainers.utility.DockerImageName.parse;
+
+@Testcontainers
+class HandleRedisCommandReplicatedEventTest {
+ @Container
+ static GenericContainer> redisContainer = new GenericContainer<>(parse("redis:latest")).withExposedPorts(6379);
+
+ @DynamicPropertySource
+ static void redisProperties(DynamicPropertyRegistry registry) {
+
+ System.out.println(registry);
+ registry.add("spring.redis.host", () -> redisContainer.getHost());
+ registry.add("spring.redis.port", () -> redisContainer.getMappedPort(6379));
+ }
+
+ @Nested
+ @SpringJUnitConfig(classes = {
+ RedisCommandReplicator.class,
+ RedisAutoConfiguration.class
+ })
+ @TestPropertySource(properties = {
+ "microsphere.redis.replicator.consumer.event.handler=REFLECT"
+ })
+ class ReflectEventHandleTest {
+ @Autowired
+ ApplicationContext applicationContext;
+
+ @Autowired
+ RedisTemplate redisTemplate;
+
+ @Test
+ void invokeMethodByReflect() {
+ String key = "Reflect";
+ String expected = "Reflect";
+ RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
+ applicationContext.publishEvent(redisCommandReplicatedEvent);
+
+ String value = redisTemplate.opsForValue().get(key);
+ assertThat(value).isEqualTo(expected);
+ }
+ }
+
+ @Nested
+ @SpringJUnitConfig(classes = {
+ RedisCommandReplicator.class,
+ RedisAutoConfiguration.class
+ })
+ @TestPropertySource(properties = {
+ "microsphere.redis.replicator.consumer.event.handler=METHOD_HANDLE"
+ })
+ class MethodHandleEventHandleTest {
+
+ @Autowired
+ ApplicationContext applicationContext;
+
+ @Autowired
+ RedisTemplate redisTemplate;
+
+ @Test
+ void invokeMethodByMethodHandle() {
+ String key = "MethodHandle";
+ String expected = "MethodHandle";
+ RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
+ applicationContext.publishEvent(redisCommandReplicatedEvent);
+
+
+ String value = redisTemplate.opsForValue().get(key);
+ assertThat(value).isEqualTo(expected);
+ }
+
+
+ }
+
+
+ private static RedisCommandReplicatedEvent getRedisCommandReplicatedEvent(String key, String value) {
+ String interfaceName = "org.springframework.data.redis.connection.RedisStringCommands";
+ String methodName = "set";
+ String[] parameterTypes = new String[]{"[B", "[B"};
+ Method method = findWriteCommandMethod(interfaceName, methodName, parameterTypes);
+
+ RedisCommandEvent redisCommandEvent = RedisCommandEvent.Builder.source("test").applicationName("test-application").method(method).args(key.getBytes(), value.getBytes()).serializationVersion(VERSION_V1).build();
+
+ return new RedisCommandReplicatedEvent(redisCommandEvent, "domain");
+ }
+
+}
From f4ed19c79756017ec5521036ddff2327b2ae4c18 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 17 Mar 2024 17:02:44 +0800
Subject: [PATCH 19/32] refactor: extract event handle interface
---
.../spring/RedisCommandReplicator.java | 32 ++++++++++++++++---
.../config/RedisReplicatorConfiguration.java | 3 +-
...dleRedisCommandReplicatedEventHandler.java | 27 ++++++++++++++++
.../RedisCommandReplicatedEventHandler.java | 14 ++++++++
...ectRedisCommandReplicatedEventHandler.java | 21 ++++++++++++
.../main/resources/META-INF/spring.factories | 6 +++-
6 files changed, 96 insertions(+), 7 deletions(-)
create mode 100644 microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
create mode 100644 microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/RedisCommandReplicatedEventHandler.java
create mode 100644 microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/ReflectRedisCommandReplicatedEventHandler.java
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/RedisCommandReplicator.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/RedisCommandReplicator.java
index 2bbaa5c..15e2471 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/RedisCommandReplicator.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/RedisCommandReplicator.java
@@ -1,17 +1,23 @@
package io.microsphere.redis.replicator.spring;
-import io.microsphere.redis.spring.event.RedisCommandEvent;
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
+import io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler;
+import io.microsphere.redis.spring.event.RedisCommandEvent;
+import io.microsphere.spring.util.SpringFactoriesLoaderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.function.Function;
+import static io.microsphere.redis.replicator.spring.config.RedisReplicatorConfiguration.CONSUMER_EVENT_HANDLE_PROPERTY_NAME;
+import static io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler.EventHandleName.REFLECT;
import static io.microsphere.redis.spring.beans.Wrapper.tryUnwrap;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.getRedisCommandBindingFunction;
@@ -23,7 +29,8 @@
* @author Mercy
* @since 1.0.0
*/
-public class RedisCommandReplicator implements ApplicationListener {
+public class RedisCommandReplicator implements ApplicationListener,
+ ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(RedisCommandReplicator.class);
@@ -35,6 +42,7 @@ public RedisCommandReplicator(RedisConnectionFactory redisConnectionFactory) {
this.redisConnectionFactory = tryUnwrap(redisConnectionFactory, RedisConnectionFactory.class);
}
+
@Override
public void onApplicationEvent(RedisCommandReplicatedEvent event) {
try {
@@ -53,12 +61,26 @@ private void handleRedisCommandEvent(RedisCommandReplicatedEvent event) throws T
Object[] args = redisCommandEvent.getArgs();
Function bindingFunction = getRedisCommandBindingFunction(interfaceNme);
Object redisCommandObject = bindingFunction.apply(redisConnection);
- // TODO: Native method implementation
- ReflectionUtils.invokeMethod(method, redisCommandObject, args);
+ // Native method implementation
+ // ReflectionUtils.invokeMethod(method, redisCommandObject, args);
+ eventHandler.handleEvent(method, redisCommandObject, args);
}
}
private RedisConnection getRedisConnection() {
return redisConnectionFactory.getConnection();
}
+
+ RedisCommandReplicatedEventHandler eventHandler;
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ String eventHandleType = applicationContext.getEnvironment()
+ .getProperty(CONSUMER_EVENT_HANDLE_PROPERTY_NAME, String.class, REFLECT.name());
+ eventHandler = SpringFactoriesLoaderUtils.loadFactories(applicationContext, RedisCommandReplicatedEventHandler.class)
+ .stream()
+ .filter(eventHandle -> eventHandle.name().equals(eventHandleType))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("No eventHandle found"));
+ }
}
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/config/RedisReplicatorConfiguration.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/config/RedisReplicatorConfiguration.java
index b7859b1..f98ac97 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/config/RedisReplicatorConfiguration.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/config/RedisReplicatorConfiguration.java
@@ -63,10 +63,11 @@ public class RedisReplicatorConfiguration implements ApplicationListener
Date: Sun, 17 Mar 2024 17:31:29 +0800
Subject: [PATCH 20/32] feat: transferMethodToMethodSignature
unImplement
---
...thodHandleRedisCommandReplicatedEventHandler.java | 6 +++---
.../HandleRedisCommandReplicatedEventTest.java | 2 ++
.../spring/metadata/RedisCommandsMethodHandles.java | 8 ++++++++
.../metadata/RedisCommandsMethodHandlesTest.java | 12 ++++++++++++
4 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
index 0bbb9e5..2ccdc5b 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
@@ -1,16 +1,16 @@
package io.microsphere.redis.replicator.spring.event.handler;
import io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles;
-import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
-import java.nio.charset.StandardCharsets;
+
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
public class MethodHandleRedisCommandReplicatedEventHandler implements RedisCommandReplicatedEventHandler {
@Override
public void handleEvent(Method method, Object redisCommandObject, Object... args) throws Throwable {
- String methodSignature = "";
+ String methodSignature = transferMethodToMethodSignature(method);
int length = args.length;
Object[] arguments = new Object[1 + args.length];
args[0] = redisCommandObject;
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index 552455c..215a702 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -2,6 +2,7 @@
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
import io.microsphere.redis.spring.event.RedisCommandEvent;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -79,6 +80,7 @@ class MethodHandleEventHandleTest {
@Autowired
RedisTemplate redisTemplate;
+ @Disabled
@Test
void invokeMethodByMethodHandle() {
String key = "MethodHandle";
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 9908121..8f9992a 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -35,6 +35,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.EnumMap;
@@ -193,6 +194,13 @@ static Class> getClassBy(Type type) {
METHOD_HANDLE_MAP = initRedisCommandMethodHandle();
}
+ public static String transferMethodToMethodSignature(Method method) {
+ // TODO 我写不出来了
+ // example RedisStringCommands#set()的方法签名:
+ // target java.lang.Boolean set(byte[] key, byte[] value);
+ return "";
+ }
+
/**
* NOTE: Use Record Class when use jdk 17+
*/
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 8a2144d..ca1a3bd 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -20,6 +20,7 @@
import java.io.IOException;
import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -30,6 +31,7 @@
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.jboss.jandex.ArrayType.builder;
@@ -90,6 +92,16 @@ void shouldThrowMethodHandleNotFoundExceptionWhenMiss() {
.isEqualTo("MissingMethodSignature");
}
+ @Test
+ void shouldTransferMethodToMethodHandleSignature() throws NoSuchMethodException {
+ MethodInfo methodInfo = getMethodInfo();
+ Method setMethod = RedisStringCommands.class.getMethod("set", byte[].class, byte[].class);
+
+ String signature = transferMethodToMethodSignature(setMethod);
+ assertThat(signature)
+ .isEqualTo(methodInfo.toString());
+ }
+
@ParameterizedTest(name = "test: {0}")
@MethodSource
void shouldGetClassWhenTypeIsPrimitiveClass(PrimitiveType primitiveType, Class> expected) {
From f24a3a01875e9e426c14e536a98b47b0e4a720fd Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Mon, 18 Mar 2024 07:44:56 +0800
Subject: [PATCH 21/32] test: MethodHandleRedisCommandReplicatedEventHandler
mock unimplemented
---
microsphere-redis-replicator-spring/pom.xml | 5 ++++
...dleRedisCommandReplicatedEventHandler.java | 2 +-
...HandleRedisCommandReplicatedEventTest.java | 30 +++++++++++++++----
3 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/microsphere-redis-replicator-spring/pom.xml b/microsphere-redis-replicator-spring/pom.xml
index 08d6ab7..f989028 100644
--- a/microsphere-redis-replicator-spring/pom.xml
+++ b/microsphere-redis-replicator-spring/pom.xml
@@ -108,6 +108,11 @@
junit-jupiter
test
+
+ org.mockito
+ mockito-inline
+ test
+
\ No newline at end of file
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
index 2ccdc5b..e5f0fba 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
@@ -13,7 +13,7 @@ public void handleEvent(Method method, Object redisCommandObject, Object... args
String methodSignature = transferMethodToMethodSignature(method);
int length = args.length;
Object[] arguments = new Object[1 + args.length];
- args[0] = redisCommandObject;
+ arguments[0] = redisCommandObject;
for (int i = 0; i < length; i++) {
arguments[i + 1] = args[i];
}
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index 215a702..3a0e787 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -2,12 +2,15 @@
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
import io.microsphere.redis.spring.event.RedisCommandEvent;
+import io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.ApplicationContext;
+import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@@ -17,11 +20,16 @@
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
+import java.io.IOException;
import java.lang.reflect.Method;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
import static io.microsphere.redis.spring.serializer.RedisCommandEventSerializer.VERSION_V1;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mockStatic;
import static org.testcontainers.utility.DockerImageName.parse;
@Testcontainers
@@ -83,14 +91,24 @@ class MethodHandleEventHandleTest {
@Disabled
@Test
void invokeMethodByMethodHandle() {
- String key = "MethodHandle";
- String expected = "MethodHandle";
- RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
- applicationContext.publishEvent(redisCommandReplicatedEvent);
+ try (MockedStatic mock = mockStatic(RedisCommandsMethodHandles.class)) {
+ Method set = RedisStringCommands.class.getMethod("set", byte[].class, byte[].class);
+ mock.when(() -> transferMethodToMethodSignature(eq(set)))
+ .thenReturn("java.lang.Boolean set(byte[] key, byte[] value)");
+ mock.when(() -> getMethodHandleBy(eq("java.lang.Boolean set(byte[] key, byte[] value)")))
+ .thenCallRealMethod();
+ String key = "MethodHandle";
+ String expected = "MethodHandle";
+ RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
+ applicationContext.publishEvent(redisCommandReplicatedEvent);
- String value = redisTemplate.opsForValue().get(key);
- assertThat(value).isEqualTo(expected);
+
+ String value = redisTemplate.opsForValue().get(key);
+ assertThat(value).isEqualTo(expected);
+ } catch (NoSuchMethodException e) {
+
+ }
}
From 431b3ff7a54f1ecbdc594d9af9d3158edb2aa33c Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 20:35:32 +0800
Subject: [PATCH 22/32] feat: implement transferMethodToMethodSignature
---
.../metadata/RedisCommandsMethodHandles.java | 72 +++++++++++++------
.../RedisCommandsMethodHandlesTest.java | 13 +++-
2 files changed, 64 insertions(+), 21 deletions(-)
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 8f9992a..549850d 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -5,6 +5,7 @@
import org.apache.commons.lang3.StringUtils;
import org.jboss.jandex.ArrayType;
import org.jboss.jandex.ClassType;
+import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
@@ -38,13 +39,18 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Function;
import java.util.stream.Collectors;
+import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.redisCommandMethodsCache;
+import static java.util.stream.Collectors.toMap;
+
public class RedisCommandsMethodHandles {
private static final Logger logger = LoggerFactory.getLogger(RedisCommandsMethodHandles.class);
@@ -54,7 +60,9 @@ public class RedisCommandsMethodHandles {
private static final ClassLoader CURRENT_CLASS_LOADER = RedisCommandsMethodHandles.class.getClassLoader();
private static final List> TARGET_CLASSES;
+ private static final Index index;
private static final Map METHOD_HANDLE_MAP;
+ private static final Map METHOD_MAP;
private RedisCommandsMethodHandles() {
}
@@ -75,6 +83,14 @@ public static MethodHandle getMethodHandleBy(String methodSignature) throws Meth
return methodHandle;
}
+ public static String transferMethodToMethodSignature(Method method) {
+ MethodInfo methodInfo = METHOD_MAP.get(method);
+ if (Objects.isNull(methodInfo)) {
+ throw new IllegalArgumentException();
+ }
+ return methodInfo.toString();
+ }
+
/**
* get all public methods from {@link RedisCommands}
* exclude {@link RedisCommands#execute}
@@ -85,30 +101,27 @@ public static MethodHandle getMethodHandleBy(String methodSignature) throws Meth
* @return List of RedisCommands all MethodInfo(include super interface)
*/
static List getAllRedisCommandMethods() {
+ Index index;
try {
- Index index = Index.of(TARGET_CLASSES);
-
- return index.getClassByName(RedisCommands.class)
- .interfaceNames()
- .stream()
- .map(index::getClassByName)
- .flatMap(classInfo -> classInfo.methods().stream())
- .filter(methodInfo -> Modifier.isPublic(methodInfo.flags()))
- .collect(Collectors.toList());
+ index = Index.of(TARGET_CLASSES);
} catch (IOException e) {
-
logger.error("Can't get RedisCommands Methods", e);
-
throw new RuntimeException("Can't get RedisCommands Methods");
}
+ return index.getClassByName(RedisCommands.class)
+ .interfaceNames()
+ .stream()
+ .map(index::getClassByName)
+ .flatMap(classInfo -> classInfo.methods().stream())
+ .filter(methodInfo -> Modifier.isPublic(methodInfo.flags()))
+ .collect(Collectors.toList());
}
static Map initRedisCommandMethodHandle() {
-
return getAllRedisCommandMethods()
.stream()
.map(methodInfo -> new MethodRecord(methodInfo.toString(), findMethodHandle(methodInfo)))
- .collect(Collectors.toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
+ .collect(toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
}
static MethodHandle findMethodHandle(MethodInfo methodInfo) {
@@ -172,6 +185,26 @@ static Class> getClassBy(Type type) {
return ClassLoaderUtils.loadClass(type.name().toString(), CURRENT_CLASS_LOADER);
}
+ static Map initRedisCommandMethodInfo() {
+ return redisCommandMethodsCache.values()
+ .stream()
+ .collect(toMap(
+ Function.identity(),
+ method -> index.getClassByName(method.getDeclaringClass())
+ .method(method.getName(), getParameterTypes(method.getParameterTypes()))
+ ));
+ }
+
+ private static Type[] getParameterTypes(Class>[] parameterTypes) {
+ return Arrays.stream(parameterTypes)
+ .map(parameterType -> {
+ if (parameterType.isArray()) {
+ return Type.create(DotName.createSimple(parameterType), Type.Kind.ARRAY);
+ } else {
+ return Type.create(DotName.createSimple(parameterType), Type.Kind.CLASS);
+ }
+ }).toArray(Type[]::new);
+ }
static {
// NOTE: use List.of() to simplify the initial logic
TARGET_CLASSES = new ArrayList<>();
@@ -191,14 +224,13 @@ static Class> getClassBy(Type type) {
TARGET_CLASSES.add(RedisGeoCommands.class);
TARGET_CLASSES.add(RedisHyperLogLogCommands.class);
+ try {
+ index = Index.of(TARGET_CLASSES);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
METHOD_HANDLE_MAP = initRedisCommandMethodHandle();
- }
-
- public static String transferMethodToMethodSignature(Method method) {
- // TODO 我写不出来了
- // example RedisStringCommands#set()的方法签名:
- // target java.lang.Boolean set(byte[] key, byte[] value);
- return "";
+ METHOD_MAP = initRedisCommandMethodInfo();
}
/**
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index ca1a3bd..bf02454 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -31,7 +31,9 @@
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodHandle;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.initRedisCommandMethodInfo;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
+import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.redisCommandMethodsCache;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.jboss.jandex.ArrayType.builder;
@@ -93,7 +95,16 @@ void shouldThrowMethodHandleNotFoundExceptionWhenMiss() {
}
@Test
- void shouldTransferMethodToMethodHandleSignature() throws NoSuchMethodException {
+ void shouldGetAllMethodInfoFromRedisCommandMethodsCache() {
+ Map map = initRedisCommandMethodInfo();
+ assertThat(map)
+ .isNotNull()
+ .hasSize(redisCommandMethodsCache.size());
+
+ }
+
+ @Test
+ void shouldTransferMethodToMethodHandleSignature() throws NoSuchMethodException, IOException {
MethodInfo methodInfo = getMethodInfo();
Method setMethod = RedisStringCommands.class.getMethod("set", byte[].class, byte[].class);
From d5a67e7519ab2fa4fcc9aadd46d11e887a03ca47 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 20:38:03 +0800
Subject: [PATCH 23/32] test: remove mock
test RedisCommandReplicatedEvent by use MethodHandleEventHandle way
---
...HandleRedisCommandReplicatedEventTest.java | 26 +++++--------------
1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index 3a0e787..686eb3c 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -88,30 +88,18 @@ class MethodHandleEventHandleTest {
@Autowired
RedisTemplate redisTemplate;
- @Disabled
+
@Test
void invokeMethodByMethodHandle() {
- try (MockedStatic mock = mockStatic(RedisCommandsMethodHandles.class)) {
- Method set = RedisStringCommands.class.getMethod("set", byte[].class, byte[].class);
- mock.when(() -> transferMethodToMethodSignature(eq(set)))
- .thenReturn("java.lang.Boolean set(byte[] key, byte[] value)");
- mock.when(() -> getMethodHandleBy(eq("java.lang.Boolean set(byte[] key, byte[] value)")))
- .thenCallRealMethod();
-
- String key = "MethodHandle";
- String expected = "MethodHandle";
- RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
- applicationContext.publishEvent(redisCommandReplicatedEvent);
-
+ String key = "MethodHandle";
+ String expected = "MethodHandle";
+ RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
+ applicationContext.publishEvent(redisCommandReplicatedEvent);
- String value = redisTemplate.opsForValue().get(key);
- assertThat(value).isEqualTo(expected);
- } catch (NoSuchMethodException e) {
- }
+ String value = redisTemplate.opsForValue().get(key);
+ assertThat(value).isEqualTo(expected);
}
-
-
}
From 757f24be05eb2552d907ebb9ff1886ef945cd499 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 21:11:34 +0800
Subject: [PATCH 24/32] refactor: refactor RedisCommandsMethodHandles
---
...dleRedisCommandReplicatedEventHandler.java | 7 +--
.../metadata/RedisCommandsMethodHandles.java | 48 ++++++++++++-------
.../RedisCommandsMethodHandlesTest.java | 4 +-
3 files changed, 35 insertions(+), 24 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
index e5f0fba..ebeea4c 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
@@ -1,23 +1,20 @@
package io.microsphere.redis.replicator.spring.event.handler;
-import io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles;
-
import java.lang.reflect.Method;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
public class MethodHandleRedisCommandReplicatedEventHandler implements RedisCommandReplicatedEventHandler {
@Override
public void handleEvent(Method method, Object redisCommandObject, Object... args) throws Throwable {
- String methodSignature = transferMethodToMethodSignature(method);
int length = args.length;
Object[] arguments = new Object[1 + args.length];
arguments[0] = redisCommandObject;
for (int i = 0; i < length; i++) {
arguments[i + 1] = args[i];
}
- RedisCommandsMethodHandles.getMethodHandleBy(methodSignature).invokeWithArguments(arguments);
+ getMethodHandleBy(method).invokeWithArguments(arguments);
}
@Override
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
index 549850d..f5f31b5 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandles.java
@@ -60,9 +60,10 @@ public class RedisCommandsMethodHandles {
private static final ClassLoader CURRENT_CLASS_LOADER = RedisCommandsMethodHandles.class.getClassLoader();
private static final List> TARGET_CLASSES;
- private static final Index index;
+ private static final Index REDIS_COMMANDS_INDEX;
private static final Map METHOD_HANDLE_MAP;
- private static final Map METHOD_MAP;
+ private static final Map METHOD_METHOD_INFO_MAP;
+ private static final Map METHOD_METHOD_HANDLE_MAP;
private RedisCommandsMethodHandles() {
}
@@ -83,8 +84,23 @@ public static MethodHandle getMethodHandleBy(String methodSignature) throws Meth
return methodHandle;
}
+ public static MethodHandle getMethodHandleBy(Method method) throws MethodHandleNotFoundException {
+ MethodHandle methodHandle = METHOD_METHOD_HANDLE_MAP.get(method);
+ if (Objects.isNull(methodHandle)) {
+ logger.error("can't find MethodHandle from RedisCommands methodSignature:{}", method.getName());
+ throw new MethodHandleNotFoundException("can't find MethodHandle from RedisCommands", method.toString());
+ }
+ return methodHandle;
+ }
+
+ /**
+ * find MethodInfo from METHOD_MAP
+ *
+ * @param method
+ * @return {@link MethodInfo#toString()}
+ */
public static String transferMethodToMethodSignature(Method method) {
- MethodInfo methodInfo = METHOD_MAP.get(method);
+ MethodInfo methodInfo = METHOD_METHOD_INFO_MAP.get(method);
if (Objects.isNull(methodInfo)) {
throw new IllegalArgumentException();
}
@@ -101,17 +117,10 @@ public static String transferMethodToMethodSignature(Method method) {
* @return List of RedisCommands all MethodInfo(include super interface)
*/
static List getAllRedisCommandMethods() {
- Index index;
- try {
- index = Index.of(TARGET_CLASSES);
- } catch (IOException e) {
- logger.error("Can't get RedisCommands Methods", e);
- throw new RuntimeException("Can't get RedisCommands Methods");
- }
- return index.getClassByName(RedisCommands.class)
+ return REDIS_COMMANDS_INDEX.getClassByName(RedisCommands.class)
.interfaceNames()
.stream()
- .map(index::getClassByName)
+ .map(REDIS_COMMANDS_INDEX::getClassByName)
.flatMap(classInfo -> classInfo.methods().stream())
.filter(methodInfo -> Modifier.isPublic(methodInfo.flags()))
.collect(Collectors.toList());
@@ -120,11 +129,11 @@ static List getAllRedisCommandMethods() {
static Map initRedisCommandMethodHandle() {
return getAllRedisCommandMethods()
.stream()
- .map(methodInfo -> new MethodRecord(methodInfo.toString(), findMethodHandle(methodInfo)))
+ .map(methodInfo -> new MethodRecord(methodInfo.toString(), findMethodHandleBy(methodInfo)))
.collect(toMap(MethodRecord::methodSignature, MethodRecord::methodHandle));
}
- static MethodHandle findMethodHandle(MethodInfo methodInfo) {
+ static MethodHandle findMethodHandleBy(MethodInfo methodInfo) {
Class> klass = getClassBy(ClassType.create(methodInfo.declaringClass().name()));
String methodName = methodInfo.name();
@@ -190,7 +199,7 @@ static Map initRedisCommandMethodInfo() {
.stream()
.collect(toMap(
Function.identity(),
- method -> index.getClassByName(method.getDeclaringClass())
+ method -> REDIS_COMMANDS_INDEX.getClassByName(method.getDeclaringClass())
.method(method.getName(), getParameterTypes(method.getParameterTypes()))
));
}
@@ -205,6 +214,7 @@ private static Type[] getParameterTypes(Class>[] parameterTypes) {
}
}).toArray(Type[]::new);
}
+
static {
// NOTE: use List.of() to simplify the initial logic
TARGET_CLASSES = new ArrayList<>();
@@ -225,12 +235,16 @@ private static Type[] getParameterTypes(Class>[] parameterTypes) {
TARGET_CLASSES.add(RedisHyperLogLogCommands.class);
try {
- index = Index.of(TARGET_CLASSES);
+ REDIS_COMMANDS_INDEX = Index.of(TARGET_CLASSES);
} catch (IOException e) {
+ logger.error("Index RedisCommands Error", e);
throw new RuntimeException(e);
}
METHOD_HANDLE_MAP = initRedisCommandMethodHandle();
- METHOD_MAP = initRedisCommandMethodInfo();
+ METHOD_METHOD_INFO_MAP = initRedisCommandMethodInfo();
+ METHOD_METHOD_HANDLE_MAP = METHOD_METHOD_INFO_MAP.keySet()
+ .stream()
+ .collect(toMap(Function.identity(), key -> METHOD_HANDLE_MAP.get(METHOD_METHOD_INFO_MAP.get(key).toString())));
}
/**
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index bf02454..2a293ff 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -26,7 +26,7 @@
import java.util.Optional;
import java.util.stream.Stream;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.findMethodHandle;
+import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.findMethodHandleBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getAllRedisCommandMethods;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getClassBy;
import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
@@ -68,7 +68,7 @@ void shouldGetMethodHandleMapFromMethodInfo() {
void shouldNewMethodHandleInstanceByMethodInfo() {
MethodInfo methodInfo = getMethodInfo();
- MethodHandle methodHandle = findMethodHandle(methodInfo);
+ MethodHandle methodHandle = findMethodHandleBy(methodInfo);
assertThat(methodHandle)
.isNotNull();
}
From 29762dc05518ed6afd3c198c87c9e0329d89c15b Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 21:13:32 +0800
Subject: [PATCH 25/32] refactor: reimport
HandleRedisCommandReplicatedEventTest
---
.../MethodHandleRedisCommandReplicatedEventHandler.java | 4 +---
.../spring/HandleRedisCommandReplicatedEventTest.java | 9 ---------
.../spring/metadata/RedisCommandsMethodHandlesTest.java | 2 +-
3 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
index ebeea4c..7d250aa 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
@@ -11,9 +11,7 @@ public void handleEvent(Method method, Object redisCommandObject, Object... args
int length = args.length;
Object[] arguments = new Object[1 + args.length];
arguments[0] = redisCommandObject;
- for (int i = 0; i < length; i++) {
- arguments[i + 1] = args[i];
- }
+ System.arraycopy(args, 0, arguments, 1, length);
getMethodHandleBy(method).invokeWithArguments(arguments);
}
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index 686eb3c..aa687b8 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -2,15 +2,11 @@
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
import io.microsphere.redis.spring.event.RedisCommandEvent;
-import io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.ApplicationContext;
-import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@@ -20,16 +16,11 @@
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
-import java.io.IOException;
import java.lang.reflect.Method;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.transferMethodToMethodSignature;
import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
import static io.microsphere.redis.spring.serializer.RedisCommandEventSerializer.VERSION_V1;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mockStatic;
import static org.testcontainers.utility.DockerImageName.parse;
@Testcontainers
diff --git a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
index 2a293ff..dad8590 100644
--- a/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
+++ b/microsphere-redis-spring/src/test/java/io/microsphere/redis/spring/metadata/RedisCommandsMethodHandlesTest.java
@@ -104,7 +104,7 @@ void shouldGetAllMethodInfoFromRedisCommandMethodsCache() {
}
@Test
- void shouldTransferMethodToMethodHandleSignature() throws NoSuchMethodException, IOException {
+ void shouldTransferMethodToMethodHandleSignature() throws NoSuchMethodException {
MethodInfo methodInfo = getMethodInfo();
Method setMethod = RedisStringCommands.class.getMethod("set", byte[].class, byte[].class);
From c08af076a4f2daa233cdfc750594167bab8daf88 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 21:21:20 +0800
Subject: [PATCH 26/32] build: jandex
jandex 3.1.6 -> 3.1.7
---
microsphere-redis-parent/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/microsphere-redis-parent/pom.xml b/microsphere-redis-parent/pom.xml
index 350ea65..3e3227f 100644
--- a/microsphere-redis-parent/pom.xml
+++ b/microsphere-redis-parent/pom.xml
@@ -28,7 +28,7 @@
3.1.6
2021.0.5.0
2021.0.7
- 3.1.6
+ 3.1.7
1.19.5
From 34f05b47e1ca422b21695334dc3b4893dd5b02ef Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Sun, 24 Mar 2024 21:22:17 +0800
Subject: [PATCH 27/32] test: remove unnecessary
---
.../spring/HandleRedisCommandReplicatedEventTest.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index aa687b8..4a06f10 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -30,8 +30,6 @@ class HandleRedisCommandReplicatedEventTest {
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
-
- System.out.println(registry);
registry.add("spring.redis.host", () -> redisContainer.getHost());
registry.add("spring.redis.port", () -> redisContainer.getMappedPort(6379));
}
From 3719ab496b5be72256401fa23248da571190644e Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Mon, 25 Mar 2024 09:46:30 +0800
Subject: [PATCH 28/32] refactor: writeCommandMethodHandlesCache
add writeCommandMethodHandlesCache
---
...dleRedisCommandReplicatedEventHandler.java | 4 +--
.../metadata/RedisMetadataRepository.java | 36 +++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
index 7d250aa..fd3b2fe 100644
--- a/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
+++ b/microsphere-redis-replicator-spring/src/main/java/io/microsphere/redis/replicator/spring/event/handler/MethodHandleRedisCommandReplicatedEventHandler.java
@@ -2,7 +2,7 @@
import java.lang.reflect.Method;
-import static io.microsphere.redis.spring.metadata.RedisCommandsMethodHandles.getMethodHandleBy;
+import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.getWriteCommandMethodHandle;
public class MethodHandleRedisCommandReplicatedEventHandler implements RedisCommandReplicatedEventHandler {
@@ -12,7 +12,7 @@ public void handleEvent(Method method, Object redisCommandObject, Object... args
Object[] arguments = new Object[1 + args.length];
arguments[0] = redisCommandObject;
System.arraycopy(args, 0, arguments, 1, length);
- getMethodHandleBy(method).invokeWithArguments(arguments);
+ getWriteCommandMethodHandle(method).invokeWithArguments(arguments);
}
@Override
diff --git a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisMetadataRepository.java b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisMetadataRepository.java
index 8580ec5..c3e4971 100644
--- a/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisMetadataRepository.java
+++ b/microsphere-redis-spring/src/main/java/io/microsphere/redis/spring/metadata/RedisMetadataRepository.java
@@ -13,6 +13,9 @@
import org.yaml.snakeyaml.Yaml;
import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -67,6 +70,12 @@ public class RedisMetadataRepository {
*/
static final Map writeCommandMethodsCache = new HashMap<>(256);
+ private static final MethodHandles.Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup();
+ /**
+ * Method Simple signature with {@link MethodHandle} object caching (reduces reflection cost)
+ */
+ static final Map writeCommandMethodHandlesCache = new HashMap<>(256);
+
/**
* MethodMetadata cache
*
@@ -227,6 +236,11 @@ public static Set getWriteCommandMethods() {
return writeCommandMethodsMetadata.keySet();
}
+ public static MethodHandle getWriteCommandMethodHandle(Method method) {
+ String id = buildCommandMethodId(method);
+ return writeCommandMethodHandlesCache.get(id);
+ }
+
/**
* Gets the {@link RedisCommands} command interface for the specified Class name {@link Class}
*
@@ -270,6 +284,7 @@ private static void initWriteCommandMethod(Method method) {
}
if (initWriteCommandMethodParameterMetadata(method, parameterTypes)) {
initWriteCommandMethodCache(method, parameterTypes);
+ initWriteCommandMethodHandleCache(method);
}
} catch (Throwable e) {
logger.error("Unable to initialize write command method[{}], Reason: {}", method, e.getMessage());
@@ -300,4 +315,25 @@ private static void initWriteCommandMethodCache(Method method, Class>[] parame
}
}
+
+ private static void initWriteCommandMethodHandleCache(Method method) {
+ String id = buildCommandMethodId(method);
+
+ MethodHandle methodHandle;
+ try {
+ methodHandle = PUBLIC_LOOKUP.findVirtual(
+ method.getDeclaringClass(),
+ method.getName(),
+ MethodType.methodType(method.getReturnType(), method.getParameterTypes()));
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ logger.error("The Redis Write Command MethodHandle[{}] can't find", id);
+ return;
+ }
+
+ if (writeCommandMethodHandlesCache.putIfAbsent(id, methodHandle) == null) {
+ logger.debug("Caches the Redis Write Command MethodHandle : {}", id);
+ } else {
+ logger.warn("The Redis Write Command MethodHandle[{}] was cached", id);
+ }
+ }
}
From 9da4aef81bd454f4f70fb4c044ed61c316e2c776 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Mon, 25 Mar 2024 20:55:15 +0800
Subject: [PATCH 29/32] test: test RedisCommandReplicatedEventHandler
add judge eventHandler
---
.../spring/HandleRedisCommandReplicatedEventTest.java | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
index 4a06f10..33a1b3d 100644
--- a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/replicator/spring/HandleRedisCommandReplicatedEventTest.java
@@ -1,6 +1,7 @@
package io.microsphere.redis.replicator.spring;
import io.microsphere.redis.replicator.spring.event.RedisCommandReplicatedEvent;
+import io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler;
import io.microsphere.redis.spring.event.RedisCommandEvent;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -49,6 +50,9 @@ class ReflectEventHandleTest {
@Autowired
RedisTemplate redisTemplate;
+ @Autowired
+ RedisCommandReplicator redisCommandReplicator;
+
@Test
void invokeMethodByReflect() {
String key = "Reflect";
@@ -56,6 +60,8 @@ void invokeMethodByReflect() {
RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
applicationContext.publishEvent(redisCommandReplicatedEvent);
+ assertThat(redisCommandReplicator.eventHandler.name())
+ .isEqualTo(RedisCommandReplicatedEventHandler.EventHandleName.REFLECT.name());
String value = redisTemplate.opsForValue().get(key);
assertThat(value).isEqualTo(expected);
}
@@ -77,6 +83,8 @@ class MethodHandleEventHandleTest {
@Autowired
RedisTemplate redisTemplate;
+ @Autowired
+ RedisCommandReplicator redisCommandReplicator;
@Test
void invokeMethodByMethodHandle() {
@@ -85,7 +93,8 @@ void invokeMethodByMethodHandle() {
RedisCommandReplicatedEvent redisCommandReplicatedEvent = getRedisCommandReplicatedEvent(key, expected);
applicationContext.publishEvent(redisCommandReplicatedEvent);
-
+ assertThat(redisCommandReplicator.eventHandler.name())
+ .isEqualTo(RedisCommandReplicatedEventHandler.EventHandleName.METHOD_HANDLE.name());
String value = redisTemplate.opsForValue().get(key);
assertThat(value).isEqualTo(expected);
}
From d99bdc92c254e0af3b5065566ea37cf8a795de84 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Fri, 29 Mar 2024 10:47:49 +0800
Subject: [PATCH 30/32] build: remove unnecessary
---
microsphere-redis-replicator-spring/pom.xml | 6 +-----
microsphere-redis-spring/pom.xml | 2 ++
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/microsphere-redis-replicator-spring/pom.xml b/microsphere-redis-replicator-spring/pom.xml
index f989028..e2dc753 100644
--- a/microsphere-redis-replicator-spring/pom.xml
+++ b/microsphere-redis-replicator-spring/pom.xml
@@ -98,16 +98,12 @@
test
-
- org.testcontainers
- testcontainers
- test
-
org.testcontainers
junit-jupiter
test
+
org.mockito
mockito-inline
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index 6150489..b5a75e1 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -107,9 +107,11 @@
mockito-inline
test
+
org.junit.jupiter
junit-jupiter
+ test
\ No newline at end of file
From 97fcf62f26fa4b3c626a8a208081116871a0fe1c Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Wed, 26 Nov 2025 20:47:17 +0800
Subject: [PATCH 31/32] build: build project
---
microsphere-redis-parent/pom.xml | 2 +-
microsphere-redis-replicator-spring/pom.xml | 4 ++--
microsphere-redis-spring/pom.xml | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/microsphere-redis-parent/pom.xml b/microsphere-redis-parent/pom.xml
index f1015e1..e315a00 100644
--- a/microsphere-redis-parent/pom.xml
+++ b/microsphere-redis-parent/pom.xml
@@ -19,7 +19,7 @@
Microsphere Redis Parent
- ${revision}
+ 0.0.1
3.1.7
1.19.5
diff --git a/microsphere-redis-replicator-spring/pom.xml b/microsphere-redis-replicator-spring/pom.xml
index e2dc753..c29768e 100644
--- a/microsphere-redis-replicator-spring/pom.xml
+++ b/microsphere-redis-replicator-spring/pom.xml
@@ -28,7 +28,7 @@
io.github.microsphere-projects
microsphere-spring-context
- ${revision}
+ 0.0.1
@@ -76,7 +76,7 @@
io.github.microsphere-projects
microsphere-spring-test
- ${revision}
+ 0.0.1
test
diff --git a/microsphere-redis-spring/pom.xml b/microsphere-redis-spring/pom.xml
index b5a75e1..e3de934 100644
--- a/microsphere-redis-spring/pom.xml
+++ b/microsphere-redis-spring/pom.xml
@@ -86,7 +86,7 @@
io.github.microsphere-projects
microsphere-spring-test
- ${revision}
+ 0.0.1
test
From 16074b25471c8b44400dd6d94ef29e6cb8bfc686 Mon Sep 17 00:00:00 2001
From: "li.qi" <15868175516@163.com>
Date: Wed, 26 Nov 2025 21:43:46 +0800
Subject: [PATCH 32/32] test: benchmark RedisCommandReplicatedEventHandler
---
microsphere-redis-parent/pom.xml | 11 +++
microsphere-redis-replicator-spring/pom.xml | 36 +++++++-
...ommandReplicatedEventHandlerBenchmark.java | 90 +++++++++++++++++++
.../benchmark/runner/BenchmarkRunner.java | 20 +++++
4 files changed, 156 insertions(+), 1 deletion(-)
create mode 100644 microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/RedisCommandReplicatedEventHandlerBenchmark.java
create mode 100644 microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/runner/BenchmarkRunner.java
diff --git a/microsphere-redis-parent/pom.xml b/microsphere-redis-parent/pom.xml
index e315a00..9a61329 100644
--- a/microsphere-redis-parent/pom.xml
+++ b/microsphere-redis-parent/pom.xml
@@ -22,6 +22,7 @@
0.0.1
3.1.7
1.19.5
+ 1.37
@@ -51,6 +52,16 @@
pom
import
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+
diff --git a/microsphere-redis-replicator-spring/pom.xml b/microsphere-redis-replicator-spring/pom.xml
index c29768e..57d81ae 100644
--- a/microsphere-redis-replicator-spring/pom.xml
+++ b/microsphere-redis-replicator-spring/pom.xml
@@ -109,6 +109,40 @@
mockito-inline
test
-
+
+ org.openjdk.jmh
+ jmh-core
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ provided
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+ benchmarks
+
+
+ org.openjdk.jmh.Main
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/RedisCommandReplicatedEventHandlerBenchmark.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/RedisCommandReplicatedEventHandlerBenchmark.java
new file mode 100644
index 0000000..8ffd432
--- /dev/null
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/RedisCommandReplicatedEventHandlerBenchmark.java
@@ -0,0 +1,90 @@
+package io.microsphere.redis.benchmark;
+
+import io.microsphere.redis.replicator.spring.event.handler.MethodHandleRedisCommandReplicatedEventHandler;
+import io.microsphere.redis.replicator.spring.event.handler.RedisCommandReplicatedEventHandler;
+import io.microsphere.redis.replicator.spring.event.handler.ReflectRedisCommandReplicatedEventHandler;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.RedisStringCommands;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.testcontainers.containers.GenericContainer;
+
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+
+import static io.microsphere.redis.spring.metadata.RedisMetadataRepository.findWriteCommandMethod;
+import static org.testcontainers.utility.DockerImageName.parse;
+
+@State(Scope.Thread)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@Warmup(iterations = 5, time = 1)
+@Measurement(iterations = 20, time = 1)
+@Fork(3)
+public class RedisCommandReplicatedEventHandlerBenchmark {
+ static GenericContainer> redisContainer;
+ RedisStringCommands redisStringCommands;
+ Method method;
+ RedisCommandReplicatedEventHandler methodHandleHandler;
+ RedisCommandReplicatedEventHandler reflectHandler;
+
+ byte[] key;
+ byte[] value;
+
+ @Setup(Level.Trial)
+ public void setup() throws Exception {
+ // 启动 PostgreSQL 容器
+ redisContainer = new GenericContainer<>(parse("redis:latest")).withExposedPorts(6379);
+ redisContainer.start();
+
+ String interfaceName = "org.springframework.data.redis.connection.RedisStringCommands";
+ String methodName = "set";
+ String[] parameterTypes = new String[]{"[B", "[B"};
+ method = findWriteCommandMethod(interfaceName, methodName, parameterTypes);
+
+ LettuceConnectionFactory redisConnectionFactory = new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisContainer.getHost(), redisContainer.getFirstMappedPort()));
+ redisConnectionFactory.afterPropertiesSet();
+ RedisConnection connection = redisConnectionFactory.getConnection();
+ redisStringCommands = connection.stringCommands();
+
+ methodHandleHandler = new MethodHandleRedisCommandReplicatedEventHandler();
+ reflectHandler = new ReflectRedisCommandReplicatedEventHandler();
+ key = "key".getBytes(StandardCharsets.UTF_8);
+ value = "value".getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Benchmark
+ public void benchmarkDirect() throws Throwable {
+ redisStringCommands.set(key, value);
+ }
+
+ @Benchmark
+ public void benchmarkMethodHandleRedisCommandReplicatedEventHandler() throws Throwable {
+ methodHandleHandler.handleEvent(method, redisStringCommands, key, value);
+ }
+
+ @Benchmark
+ public void benchmarkReflectRedisCommandReplicatedEventHandler() throws Throwable {
+ reflectHandler.handleEvent(method, redisStringCommands, key, value);
+ }
+
+ @TearDown(Level.Trial)
+ public void tearDown() throws Exception {
+ if (redisContainer != null) {
+ redisContainer.stop();
+ }
+ }
+}
diff --git a/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/runner/BenchmarkRunner.java b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/runner/BenchmarkRunner.java
new file mode 100644
index 0000000..d018d22
--- /dev/null
+++ b/microsphere-redis-replicator-spring/src/test/java/io/microsphere/redis/benchmark/runner/BenchmarkRunner.java
@@ -0,0 +1,20 @@
+package io.microsphere.redis.benchmark.runner;
+
+import io.microsphere.redis.benchmark.RedisCommandReplicatedEventHandlerBenchmark;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+public class BenchmarkRunner {
+ public static void main(String[] args) throws RunnerException {
+ Options options = new OptionsBuilder()
+ .include(RedisCommandReplicatedEventHandlerBenchmark.class.getSimpleName())
+ .warmupIterations(3)
+ .measurementIterations(5)
+ .forks(1)
+ .build();
+
+ new Runner(options).run();
+ }
+}