Browse Source

feat(core): 尝试修复ISSUE:I13Y8Y

https://gitee.com/baomidou/mybatis-plus/issues/I13Y8Y
由于 Java
本本身的关系,这个干不了
hanchunlin 5 years ago
parent
commit
5323a2f82c

+ 1 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractLambdaWrapper.java

@@ -86,7 +86,7 @@ public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWr
      */
     private String getColumn(SerializedLambda lambda, boolean onlyColumn) throws MybatisPlusException {
         String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
-        Class aClass = lambda.getInstantiatedMethodType();
+        Class aClass = lambda.getInstantiatedType();
         if (!initColumnMap) {
             columnMap = LambdaUtils.getColumnMap(aClass);
         }

+ 15 - 15
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/SerializedLambda.java

@@ -20,8 +20,6 @@ import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
 
 import java.io.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * 这个类是从 {@link java.lang.invoke.SerializedLambda} 里面 copy 过来的,
@@ -76,7 +74,7 @@ public class SerializedLambda implements Serializable {
      * @return 返回 class 名称
      */
     public String getFunctionalInterfaceClassName() {
-        return normalName(functionalInterfaceClass);
+        return normalizedName(functionalInterfaceClass);
     }
 
     /**
@@ -94,7 +92,7 @@ public class SerializedLambda implements Serializable {
      * @return 类名
      */
     public String getImplClassName() {
-        return normalName(implClass);
+        return normalizedName(implClass);
     }
 
     /**
@@ -112,18 +110,16 @@ public class SerializedLambda implements Serializable {
      * @param name 名称
      * @return 正常的类名
      */
-    private String normalName(String name) {
+    private String normalizedName(String name) {
         return name.replace('/', '.');
     }
 
-    private static final Pattern INSTANTIATED_METHOD_TYPE = Pattern.compile("\\(L(?<instantiatedMethodType>[\\S&&[^;)]]+);\\)L[\\S]+;");
-
-    public Class getInstantiatedMethodType() {
-        Matcher matcher = INSTANTIATED_METHOD_TYPE.matcher(instantiatedMethodType);
-        if (matcher.find()) {
-            return ClassUtils.toClassConfident(normalName(matcher.group("instantiatedMethodType")));
-        }
-        throw ExceptionUtils.mpe("无法从 %s 解析调用实例。。。", instantiatedMethodType);
+    /**
+     * @return 获取实例化方法的类型
+     */
+    public Class getInstantiatedType() {
+        String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')));
+        return ClassUtils.toClassConfident(instantiatedTypeName);
     }
 
     /**
@@ -131,8 +127,12 @@ public class SerializedLambda implements Serializable {
      */
     @Override
     public String toString() {
-        return String.format("%s -> %s::%s", getFunctionalInterfaceClassName(), getImplClass().getSimpleName(),
-            implMethodName);
+        String interfaceName = getFunctionalInterfaceClassName();
+        String implName = getImplClassName();
+        return String.format("%s -> %s::%s",
+                interfaceName.substring(interfaceName.lastIndexOf('.') + 1),
+                implName.substring(implName.lastIndexOf('.') + 1),
+                implMethodName);
     }
 
 }

+ 37 - 5
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtilsTest.java

@@ -21,6 +21,8 @@ import org.apache.ibatis.reflection.property.PropertyNamer;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
 /**
  * 测试 Lambda 解析类
  */
@@ -32,9 +34,15 @@ class LambdaUtilsTest {
     @Test
     void testResolve() {
         SerializedLambda lambda = LambdaUtils.resolve(TestModel::getId);
-        Assertions.assertEquals(TestModel.class.getName(), lambda.getImplClassName());
-        Assertions.assertEquals("getId", lambda.getImplMethodName());
-        Assertions.assertEquals("id", PropertyNamer.methodToProperty(lambda.getImplMethodName()));
+        assertEquals(Parent.class.getName(), lambda.getImplClassName());
+        assertEquals("getId", lambda.getImplMethodName());
+        assertEquals("id", PropertyNamer.methodToProperty(lambda.getImplMethodName()));
+        assertEquals(TestModel.class, lambda.getInstantiatedType());
+
+        // 测试接口泛型获取
+        lambda = new TestModelHolder().toLambda();
+        // 无法从泛型获取到实现类,即使改泛型参数已经被实现
+        assertEquals(Named.class, lambda.getInstantiatedType());
     }
 
     /**
@@ -52,12 +60,36 @@ class LambdaUtilsTest {
      * @param lambda 解析后的 lambda
      */
     private void assertInstantiatedMethodTypeIsReference(SerializedLambda lambda) {
-        Assertions.assertNotNull(lambda.getInstantiatedMethodType());
+        Assertions.assertNotNull(lambda.getInstantiatedType());
+    }
+
+    /**
+     * 用于测试的 Model
+     */
+    @Getter
+    private static class TestModel extends Parent implements Named {
+        private String name;
     }
 
     @Getter
-    private static class TestModel {
+    private static abstract class Parent {
         private int id;
     }
 
+    // 处理 ISSUE:https://gitee.com/baomidou/mybatis-plus/issues/I13Y8Y,由于 java 本身处理的问题,这里无法获取到实例
+    private abstract static class BaseHolder<T extends Named> {
+
+        SerializedLambda toLambda() {
+            return LambdaUtils.resolve(T::getName);
+        }
+
+    }
+
+    private static class TestModelHolder extends BaseHolder<TestModel> {
+    }
+
+    private interface Named {
+        String getName();
+    }
+
 }