Pārlūkot izejas kodu

完成简单 lambda 解析代码,但为运行单元测试

HCL 7 gadi atpakaļ
vecāks
revīzija
dd84378fe0

+ 1 - 0
mybatis-plus-core/build.gradle

@@ -6,6 +6,7 @@ dependencies {
     compile project(":mybatis-plus-annotation")
     compile rootProject.ext.dependencies["mybatis"]
     compile rootProject.ext.dependencies["jsqlparser"]
+    compile rootProject.ext.dependencies["lombok"]
     compile group: 'com.trigersoft', name: 'jaque', version: '2.1.2'
 
     testCompile rootProject.ext.dependencies["mybatis-ehcache"]

+ 43 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtils.java

@@ -0,0 +1,43 @@
+package com.baomidou.mybatisplus.core.toolkit;
+
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.Optional;
+import java.util.WeakHashMap;
+
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedFunction;
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+
+/**
+ * Lambda 工具类
+ *
+ * @author HCL
+ * @Date 2018/05/10
+ */
+public final class LambdaUtils {
+
+    // 做个小小的缓存
+    private static final Map<Class, WeakReference<SerializedLambda>> CACHE = new WeakHashMap<>();
+
+    private LambdaUtils() {
+    }
+
+    /**
+     * 解析 lambda 表达式
+     *
+     * @param func 需要解析的 lambda 对象
+     * @param <T>  类型,被调用的 Function 对象的目标类型
+     * @return 返回解析后的结果
+     */
+    public static <T> SerializedLambda resolve(SerializedFunction<T, ?> func) {
+        Class clazz = func.getClass();
+        return Optional.ofNullable(CACHE.get(clazz))
+            .map(WeakReference::get)
+            .orElseGet(() -> {
+                SerializedLambda lambda = SerializedLambda.convert(func);
+                CACHE.put(clazz, new WeakReference<>(lambda));
+                return lambda;
+            });
+    }
+
+}

+ 2 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/package-info.java

@@ -1,4 +1,6 @@
 /**
  * 工具类
+ *
+ * @see com.baomidou.mybatisplus.core.toolkit.LambdaUtils Lambda工具类
  */
 package com.baomidou.mybatisplus.core.toolkit;

+ 16 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/SerializedFunction.java

@@ -0,0 +1,16 @@
+package com.baomidou.mybatisplus.core.toolkit.support;
+
+import java.io.Serializable;
+import java.util.function.Function;
+
+/**
+ * 主要是为了实现序列化接口
+ * <p>
+ *
+ * @author HCL
+ * @Date 2018/05/10
+ */
+@FunctionalInterface
+public interface SerializedFunction<T, R> extends Function<T, R>, Serializable {
+
+}

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

@@ -0,0 +1,63 @@
+package com.baomidou.mybatisplus.core.toolkit.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
+
+import lombok.Getter;
+
+/**
+ * 这个类是从 {@link java.lang.invoke.SerializedLambda} 里面 copy 过来的
+ * 字段信息完全一样
+ * <p>
+ * 负责将一个支持序列的 Function 序列化为 SerializedLambda
+ *
+ * @author HCL
+ * @Date 2018/05/10
+ */
+@Getter
+public class SerializedLambda implements Serializable {
+
+    private static final long serialVersionUID = 8025925345765570181L;
+    private Class<?> capturingClass;
+    private String functionalInterfaceClass;
+    private String functionalInterfaceMethodName;
+    private String functionalInterfaceMethodSignature;
+    private String implClass;
+    private String implMethodName;
+    private String implMethodSignature;
+    private int implMethodKind;
+    private String instantiatedMethodType;
+    private Object[] capturedArgs;
+
+    /**
+     * 通过反序列化转换 class
+     *
+     * @param lambda lambda对象
+     * @return 返回解析后的 SerializedLambda
+     */
+    public static SerializedLambda convert(SerializedFunction lambda) {
+        byte[] bytes = SerializationUtils.serialize(lambda);
+        try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(bytes)) {
+            @Override
+            protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
+                Class<?> clazz = super.resolveClass(objectStreamClass);
+                return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
+            }
+        }) {
+            return (SerializedLambda) objIn.readObject();
+        } catch (ClassNotFoundException | IOException e) {
+            throw new MybatisPlusException("This is impossible to happen", e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "implClass".replace("/", ".") + "#" + implMethodName;
+    }
+}

+ 25 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtilsTest.java

@@ -0,0 +1,25 @@
+package com.baomidou.mybatisplus.core.toolkit;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+
+import lombok.Getter;
+
+public class LambdaUtilsTest {
+
+    @Test
+    public void testResolve() {
+        SerializedLambda lambda = LambdaUtils.resolve(TestPojo::getId);
+        Assert.assertEquals(TestPojo.class.getName(), lambda.getImplClass().replace("/", "."));
+        Assert.assertEquals("getId", lambda.getImplMethodName());
+    }
+
+    @Getter
+    private class TestPojo {
+
+        private int id;
+    }
+
+}