Browse Source

!184 java 17 的支持
Merge pull request !184 from 如梦技术/3.0

青苗 3 years ago
parent
commit
42f434ec62

+ 8 - 17
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtils.java

@@ -15,13 +15,11 @@
  */
 package com.baomidou.mybatisplus.core.toolkit;
 
-import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.support.*;
 
 import java.lang.invoke.SerializedLambda;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.Map;
@@ -50,24 +48,17 @@ public final class LambdaUtils {
      * @return 返回解析后的结果
      */
     public static <T> LambdaMeta extract(SFunction<T, ?> func) {
+        // 1. IDEA 调试模式下 lambda 表达式是一个代理
+        if (func instanceof Proxy) {
+            return new IdeaProxyLambdaMeta((Proxy) func);
+        }
+        // 2. 反射读取
         try {
             Method method = func.getClass().getDeclaredMethod("writeReplace");
             return new ReflectLambdaMeta((SerializedLambda) ReflectionKit.setAccessible(method).invoke(func));
-        } catch (NoSuchMethodException e) {
-            // IDEA 调试模式下 lambda 表达式是一个代理
-            if (func instanceof Proxy) return new IdeaProxyLambdaMeta((Proxy) func);
-            String message = "Cannot find method writeReplace, please make sure that the lambda composite class is currently passed in";
-            throw new MybatisPlusException(message);
-        } catch (InvocationTargetException | IllegalAccessException e) {
-            throw new MybatisPlusException(e);
-        } catch (Error e) {
-            // JDK 16 模块化后不能使用反射访问其他模块的字段,因此这里需要使用序列化的方式进行处理
-            // https://gitee.com/baomidou/mybatis-plus/issues/I3XDT9
-            Throwable cause = e.getCause();
-            if (cause != null && cause.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
-                return new ShadowLambdaMeta(com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda.extract(func));
-            }
-            throw e;
+        } catch (Throwable e) {
+            // 3. 反射失败使用序列化的方式读取
+            return new ShadowLambdaMeta(com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda.extract(func));
         }
     }
 

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

@@ -3,6 +3,7 @@ package com.baomidou.mybatisplus.core.toolkit.support;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import lombok.extern.slf4j.Slf4j;
 
 import java.lang.invoke.SerializedLambda;
 import java.lang.reflect.Field;
@@ -10,16 +11,21 @@ import java.lang.reflect.Field;
 /**
  * Created by hcl at 2021/5/14
  */
+@Slf4j
 public class ReflectLambdaMeta implements LambdaMeta {
     private static final Field FIELD_CAPTURING_CLASS;
 
     static {
+        Field fieldCapturingClass;
         try {
             Class<SerializedLambda> aClass = SerializedLambda.class;
-            FIELD_CAPTURING_CLASS = ReflectionKit.setAccessible(aClass.getDeclaredField("capturingClass"));
-        } catch (NoSuchFieldException e) {
-            throw new MybatisPlusException(e);
+            fieldCapturingClass = ReflectionKit.setAccessible(aClass.getDeclaredField("capturingClass"));
+        } catch (Throwable e) {
+            // 解决高版本 jdk 的问题 gitee: https://gitee.com/baomidou/mybatis-plus/issues/I4A7I5
+            log.warn(e.getMessage());
+            fieldCapturingClass = null;
         }
+        FIELD_CAPTURING_CLASS = fieldCapturingClass;
     }
 
     private final SerializedLambda lambda;
@@ -37,12 +43,16 @@ public class ReflectLambdaMeta implements LambdaMeta {
     public Class<?> getInstantiatedClass() {
         String instantiatedMethodType = lambda.getInstantiatedMethodType();
         String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')).replace('/', '.');
-        return ClassUtils.toClassConfident(instantiatedType, getCapturingClass().getClassLoader());
+        return ClassUtils.toClassConfident(instantiatedType, getCapturingClassClassLoader());
     }
 
-    public Class<?> getCapturingClass() {
+    private ClassLoader getCapturingClassClassLoader() {
+        // 如果反射失败,使用默认的 classloader
+        if (FIELD_CAPTURING_CLASS == null) {
+            return null;
+        }
         try {
-            return (Class<?>) FIELD_CAPTURING_CLASS.get(lambda);
+            return ((Class<?>) FIELD_CAPTURING_CLASS.get(lambda)).getClassLoader();
         } catch (IllegalAccessException e) {
             throw new MybatisPlusException(e);
         }