+ *
+ * @param name 类名称
+ * @return 返回转换后的 Class
+ */
+ public static Class> toClassConfident(String name) {
+ return toClassConfident(name, null);
+ }
+
+ /**
+ * @param name
+ * @param classLoader
+ * @return
+ * @since 3.4.3
+ */
+ public static Class> toClassConfident(String name, ClassLoader classLoader) {
+ try {
+ return loadClass(name, getClassLoaders(classLoader));
+ } catch (ClassNotFoundException e) {
+ throw ExceptionUtils.mpe("找不到指定的class!请仅在明确确定会有 class 的时候,调用该方法", e);
+ }
+ }
+
+ private static Class> loadClass(String className, ClassLoader[] classLoaders) throws ClassNotFoundException {
+ for (ClassLoader classLoader : classLoaders) {
+ if (classLoader != null) {
+ try {
+ return Class.forName(className, true, classLoader);
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ }
+ }
+ throw new ClassNotFoundException("Cannot find class: " + className);
+ }
+
+
+ /**
+ * Determine the name of the package of the given class,
+ * e.g. "java.lang" for the {@code java.lang.String} class.
+ *
+ * @param clazz the class
+ * @return the package name, or the empty String if the class
+ * is defined in the default package
+ */
+ public static String getPackageName(Class> clazz) {
+ Assert.notNull(clazz, "Class must not be null");
+ return getPackageName(clazz.getName());
+ }
+
+ /**
+ * Determine the name of the package of the given fully-qualified class name,
+ * e.g. "java.lang" for the {@code java.lang.String} class name.
+ *
+ * @param fqClassName the fully-qualified class name
+ * @return the package name, or the empty String if the class
+ * is defined in the default package
+ */
+ public static String getPackageName(String fqClassName) {
+ Assert.notNull(fqClassName, "Class name must not be null");
+ int lastDotIndex = fqClassName.lastIndexOf(StringPool.DOT);
+ return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : StringPool.EMPTY);
+ }
+
+ /**
+ * Return the default ClassLoader to use: typically the thread context
+ * ClassLoader, if available; the ClassLoader that loaded the ClassUtils
+ * class will be used as fallback.
+ *
Call this method if you intend to use the thread context ClassLoader
+ * in a scenario where you clearly prefer a non-null ClassLoader reference:
+ * for example, for class path resource loading (but not necessarily for
+ * {@code Class.forName}, which accepts a {@code null} ClassLoader
+ * reference as well).
+ *
+ * @return the default ClassLoader (only {@code null} if even the system
+ * ClassLoader isn't accessible)
+ * @see Thread#getContextClassLoader()
+ * @see ClassLoader#getSystemClassLoader()
+ * @since 3.3.2
+ */
+ @Deprecated
+ public static ClassLoader getDefaultClassLoader() {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (Throwable ex) {
+ // Cannot access thread context ClassLoader - falling back...
+ }
+ if (cl == null) {
+ // No thread context class loader -> use class loader of this class.
+ cl = ClassUtils.class.getClassLoader();
+ if (cl == null) {
+ // getClassLoader() returning null indicates the bootstrap ClassLoader
+ try {
+ cl = ClassLoader.getSystemClassLoader();
+ } catch (Throwable ex) {
+ // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
+ }
+ }
+ }
+ return cl;
+ }
+
+ private static ClassLoader[] getClassLoaders(ClassLoader classLoader) {
+ return new ClassLoader[]{
+ classLoader,
+ Resources.getDefaultClassLoader(),
+ Thread.currentThread().getContextClassLoader(),
+ ClassUtils.class.getClassLoader(),
+ systemClassLoader};
+ }
+}
diff --git a/src/main/java/com/github/yulichang/toolkit/Constant.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/Constant.java
similarity index 100%
rename from src/main/java/com/github/yulichang/toolkit/Constant.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/Constant.java
diff --git a/src/main/java/com/github/yulichang/toolkit/InterceptorList.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java
similarity index 98%
rename from src/main/java/com/github/yulichang/toolkit/InterceptorList.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java
index e8620cc..c113632 100644
--- a/src/main/java/com/github/yulichang/toolkit/InterceptorList.java
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/InterceptorList.java
@@ -13,7 +13,7 @@ import java.util.function.Predicate;
* 保证 MPJInterceptor 再最后一个(第一个执行)
*
* @author yulichang
- * @since 1.2.5
+ * @since 1.3.0
*/
public class InterceptorList extends ArrayList {
diff --git a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java
similarity index 63%
rename from src/main/java/com/github/yulichang/toolkit/LambdaUtils.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java
index e782640..9e782cd 100644
--- a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java
@@ -5,13 +5,13 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import com.github.yulichang.toolkit.support.ColumnCache;
-import com.github.yulichang.toolkit.support.SerializedLambda;
+import com.github.yulichang.toolkit.support.*;
import org.apache.ibatis.reflection.property.PropertyNamer;
-import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import static java.util.Locale.ENGLISH;
@@ -19,50 +19,54 @@ import static java.util.Locale.ENGLISH;
/**
* copy {@link com.baomidou.mybatisplus.core.toolkit.LambdaUtils}
*/
+@SuppressWarnings("unused")
public final class LambdaUtils {
/* ******* 自定义方法 *********** */
public static String getName(SFunction fn) {
- return PropertyNamer.methodToProperty(resolve(fn).getImplMethodName());
+ LambdaMeta extract = extract(fn);
+ String name = PropertyNamer.methodToProperty(extract.getImplMethodName());
+ if (Character.isUpperCase(name.charAt(0))) {
+ Map map = MPJReflectionKit.getFieldMap(extract.getInstantiatedClass());
+ if (map.containsKey(name)) {
+ return name;
+ } else {
+ return map.keySet().stream().filter(i -> i.equalsIgnoreCase(name)).findFirst().orElse(null);
+ }
+ }
+ return name;
}
@SuppressWarnings("unchecked")
public static Class getEntityClass(SFunction fn) {
- return (Class) resolve(fn).getInstantiatedType();
+ return (Class) extract(fn).getInstantiatedClass();
}
/* ******* 自定义方法 结束 以下代码均为拷贝 *********** */
- /**
- * 字段映射
- */
private static final Map> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();
/**
- * SerializedLambda 反序列化缓存
- */
- private static final Map> FUNC_CACHE = new ConcurrentHashMap<>();
-
- /**
- * 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。
* 该缓存可能会在任意不定的时间被清除
*
* @param func 需要解析的 lambda 对象
* @param 类型,被调用的 Function 对象的目标类型
* @return 返回解析后的结果
- * @see SerializedLambda#resolve(SFunction)
*/
- public static SerializedLambda resolve(SFunction func) {
- Class> clazz = func.getClass();
- String name = clazz.getName();
- return Optional.ofNullable(FUNC_CACHE.get(name))
- .map(WeakReference::get)
- .orElseGet(() -> {
- SerializedLambda lambda = SerializedLambda.resolve(func);
- FUNC_CACHE.put(name, new WeakReference<>(lambda));
- return lambda;
- });
+ public static LambdaMeta extract(SFunction func) {
+ // 1. IDEA 调试模式下 lambda 表达式是一个代理
+ if (func instanceof Proxy) {
+ return new IdeaProxyLambdaMeta((Proxy) func);
+ }
+ // 2. 反射读取
+ try {
+ Method method = func.getClass().getDeclaredMethod("writeReplace");
+ return new ReflectLambdaMeta((java.lang.invoke.SerializedLambda) ReflectionKit.setAccessible(method).invoke(func));
+ } catch (Throwable e) {
+ // 3. 反射失败使用序列化的方式读取
+ return new ShadowLambdaMeta(SerializedLambda.extract(func));
+ }
}
/**
@@ -79,6 +83,14 @@ public final class LambdaUtils {
return key.toUpperCase(ENGLISH);
}
+ /**
+ * 将传入的表信息加入缓存
+ *
+ * @param tableInfo 表信息
+ */
+ public static void installCache(TableInfo tableInfo) {
+ COLUMN_CACHE_MAP.put(tableInfo.getEntityType().getName(), createColumnCacheMap(tableInfo));
+ }
/**
* 缓存实体字段 MAP 信息
@@ -115,5 +127,4 @@ public final class LambdaUtils {
return info == null ? null : createColumnCacheMap(info);
});
}
-
}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LogicInfoUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LogicInfoUtils.java
new file mode 100644
index 0000000..bfd1dce
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/LogicInfoUtils.java
@@ -0,0 +1,45 @@
+package com.github.yulichang.toolkit;
+
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 逻辑删除信息类
+ *
+ * @author yulichang
+ * @since 1.3.7
+ */
+public class LogicInfoUtils implements Constants {
+
+ private static final Map, String> LOGIC_CACHE = new ConcurrentHashMap<>();
+
+
+ @SuppressWarnings("ConstantConditions")
+ public static String getLogicInfo(int tableIndex, Class> clazz) {
+ String logicStr = LOGIC_CACHE.get(clazz);
+ if (Objects.nonNull(logicStr)) {
+ return logicStr;
+ }
+ TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+ Assert.notNull(tableInfo, "%s 不是数据库实体或没有注册到mybatis plus中", clazz.getName());
+ if (tableInfo.isWithLogicDelete() && Objects.nonNull(tableInfo.getLogicDeleteFieldInfo())) {
+ final String value = tableInfo.getLogicDeleteFieldInfo().getLogicNotDeleteValue();
+ if (NULL.equalsIgnoreCase(value)) {
+ logicStr = " AND " + Constant.TABLE_ALIAS + tableIndex + DOT + tableInfo.getLogicDeleteFieldInfo().getColumn() + " IS NULL";
+ } else {
+ logicStr = " AND " + Constant.TABLE_ALIAS + tableIndex + DOT + tableInfo.getLogicDeleteFieldInfo().getColumn() + EQUALS + String.format(tableInfo.getLogicDeleteFieldInfo().isCharSequence() ? "'%s'" : "%s", value);
+ }
+ } else {
+ logicStr = StringPool.EMPTY;
+ }
+ LOGIC_CACHE.put(clazz, logicStr);
+ return logicStr;
+ }
+}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java
new file mode 100644
index 0000000..1f923e4
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJReflectionKit.java
@@ -0,0 +1,62 @@
+package com.github.yulichang.toolkit;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 反射工具类
+ *
+ * @author yulichang
+ * @since 1.3.7
+ */
+@SuppressWarnings("unused")
+public final class MPJReflectionKit {
+
+ private static final Map, Map> CLASS_FIELD_CACHE = new ConcurrentHashMap<>();
+
+ private static final Map EMPTY_MAP = new HashMap<>();
+
+ /**
+ * Collection字段的泛型
+ */
+ public static Class> getGenericType(Field field) {
+ Type type = field.getGenericType();
+ //没有写泛型
+ if (!(type instanceof ParameterizedType)) {
+ return Object.class;
+ }
+ ParameterizedType pt = (ParameterizedType) type;
+ Type[] actualTypeArguments = pt.getActualTypeArguments();
+ Type argument = actualTypeArguments[0];
+ //通配符泛型 ? , ? extends XXX , ? super XXX
+ if (argument instanceof WildcardType) {
+ //获取上界
+ Type[] types = ((WildcardType) argument).getUpperBounds();
+ return (Class>) types[0];
+ }
+ return (Class>) argument;
+ }
+
+ /**
+ * 获取该类的所有属性列表
+ *
+ * @param clazz 反射类
+ */
+ public static Map getFieldMap(Class> clazz) {
+ if (clazz == null) {
+ return EMPTY_MAP;
+ }
+ Map fieldMap = CLASS_FIELD_CACHE.get(clazz);
+ if (fieldMap != null) {
+ return fieldMap;
+ }
+ Map map = ReflectionKit.getFieldMap(clazz);
+ CLASS_FIELD_CACHE.put(clazz, map);
+ return map;
+ }
+}
diff --git a/src/main/java/com/github/yulichang/toolkit/MPJWrappers.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJWrappers.java
similarity index 100%
rename from src/main/java/com/github/yulichang/toolkit/MPJWrappers.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/MPJWrappers.java
diff --git a/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java
similarity index 74%
rename from src/main/java/com/github/yulichang/toolkit/ReflectionKit.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java
index e7b663d..d9d92a8 100644
--- a/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,17 +15,16 @@
*/
package com.github.yulichang.toolkit;
-import com.baomidou.mybatisplus.core.toolkit.Assert;
-import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
-import org.springframework.core.GenericTypeResolver;
+import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
-import java.lang.reflect.*;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -39,14 +38,14 @@ import static java.util.stream.Collectors.toMap;
* @author hcl
* @since 2016-09-22
*/
-@SuppressWarnings("unused")
+@SuppressWarnings("All")
public final class ReflectionKit {
- private static final Log logger = LogFactory.getLog(ReflectionKit.class);
/**
* class field cache
*/
private static final Map, List> CLASS_FIELD_CACHE = new ConcurrentHashMap<>();
+ @Deprecated
private static final Map, Class>> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(8);
private static final Map, Class>> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap<>(8);
@@ -96,32 +95,11 @@ public final class ReflectionKit {
* @return Class
*/
public static Class> getSuperClassGenericType(final Class> clazz, final Class> genericIfc, final int index) {
- Class>[] typeArguments = GenericTypeResolver.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc);
+ //update by noear @2021-09-03
+ Class>[] typeArguments = GenericTypeUtils.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc);
return null == typeArguments ? null : typeArguments[index];
}
-
- /**
- * Collection字段的泛型
- */
- public static Class> getGenericType(Field field) {
- Type type = field.getGenericType();
- //没有写泛型
- if (!(type instanceof ParameterizedType)) {
- return Object.class;
- }
- ParameterizedType pt = (ParameterizedType) type;
- Type[] actualTypeArguments = pt.getActualTypeArguments();
- Type argument = actualTypeArguments[0];
- //通配符泛型 ? , ? extends XXX , ? super XXX
- if (argument instanceof WildcardType) {
- //获取上界
- Type[] types = ((WildcardType) argument).getUpperBounds();
- return (Class>) types[0];
- }
- return (Class>) argument;
- }
-
/**
*
* 获取该类的所有属性列表
@@ -131,7 +109,7 @@ public final class ReflectionKit {
*/
public static Map getFieldMap(Class> clazz) {
List fieldList = getFieldList(clazz);
- return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, field -> field)) : Collections.emptyMap();
+ return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, Function.identity())) : Collections.emptyMap();
}
/**
@@ -162,11 +140,11 @@ public final class ReflectionKit {
* 中间表实体重写父类属性 ` private transient Date createTime; `
*/
return fieldMap.values().stream()
- /* 过滤静态属性 */
- .filter(f -> !Modifier.isStatic(f.getModifiers()))
- /* 过滤 transient关键字修饰的属性 */
- .filter(f -> !Modifier.isTransient(f.getModifiers()))
- .collect(Collectors.toList());
+ /* 过滤静态属性 */
+ .filter(f -> !Modifier.isStatic(f.getModifiers()))
+ /* 过滤 transient关键字修饰的属性 */
+ .filter(f -> !Modifier.isTransient(f.getModifiers()))
+ .collect(Collectors.toList());
});
}
@@ -181,12 +159,12 @@ public final class ReflectionKit {
public static Map excludeOverrideSuperField(Field[] fields, List superFieldList) {
// 子类属性
Map fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity(),
- (u, v) -> {
- throw new IllegalStateException(String.format("Duplicate key %s", u));
- },
- LinkedHashMap::new));
+ (u, v) -> {
+ throw new IllegalStateException(String.format("Duplicate key %s", u));
+ },
+ LinkedHashMap::new));
superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName()))
- .forEach(f -> fieldMap.put(f.getName(), f));
+ .forEach(f -> fieldMap.put(f.getName(), f));
return fieldMap;
}
@@ -196,6 +174,7 @@ public final class ReflectionKit {
* @param clazz class
* @return 是否基本类型或基本包装类型
*/
+ @Deprecated
public static boolean isPrimitiveOrWrapper(Class> clazz) {
Assert.notNull(clazz, "Class must not be null");
return (clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz));
@@ -204,4 +183,16 @@ public final class ReflectionKit {
public static Class> resolvePrimitiveIfNecessary(Class> clazz) {
return (clazz.isPrimitive() && clazz != void.class ? PRIMITIVE_TYPE_TO_WRAPPER_MAP.get(clazz) : clazz);
}
+
+ /**
+ * 设置可访问对象的可访问权限为 true
+ *
+ * @param object 可访问的对象
+ * @param 类型
+ * @return 返回设置后的对象
+ */
+ public static T setAccessible(T object) {
+ return AccessController.doPrivileged(new SetAccessibleAction<>(object));
+ }
+
}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java
new file mode 100644
index 0000000..7067b9b
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java
@@ -0,0 +1,26 @@
+package com.github.yulichang.toolkit;
+
+
+/**
+ * spring容器工具类
+ *
+ * @author yulichang
+ * @since 1.2.0
+ */
+public class SpringContentUtils {
+
+ private static SpringContext springContext;
+
+ public SpringContentUtils(SpringContext springContext) {
+ SpringContentUtils.springContext = springContext;
+ }
+
+ public static T getBean(Class clazz) {
+ return SpringContentUtils.springContext.getBean(clazz);
+ }
+
+ public interface SpringContext {
+
+ T getBean(Class clazz);
+ }
+}
diff --git a/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java
similarity index 100%
rename from src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java
diff --git a/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java
similarity index 98%
rename from src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java
index 2d4df23..9a4c95c 100644
--- a/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java
@@ -8,7 +8,7 @@ import lombok.Getter;
*
* @author yulichang
* @see com.baomidou.mybatisplus.core.toolkit.support.ColumnCache
- * @since 1.2.5
+ * @since 1.3.0
*/
public class ColumnCache extends com.baomidou.mybatisplus.core.toolkit.support.ColumnCache {
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java
new file mode 100644
index 0000000..a4c3482
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/IdeaProxyLambdaMeta.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.yulichang.toolkit.support;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+/**
+ * 在 IDEA 的 Evaluate 中执行的 Lambda 表达式元数据需要使用该类处理元数据
+ *
+ * Create by hcl at 2021/5/17
+ */
+public class IdeaProxyLambdaMeta implements LambdaMeta {
+ private static final Field FIELD_MEMBER_NAME;
+ private static final Field FIELD_MEMBER_NAME_CLAZZ;
+ private static final Field FIELD_MEMBER_NAME_NAME;
+
+ static {
+ try {
+ Class> classDirectMethodHandle = Class.forName("java.lang.invoke.DirectMethodHandle");
+ FIELD_MEMBER_NAME = ReflectionKit.setAccessible(classDirectMethodHandle.getDeclaredField("member"));
+ Class> classMemberName = Class.forName("java.lang.invoke.MemberName");
+ FIELD_MEMBER_NAME_CLAZZ = ReflectionKit.setAccessible(classMemberName.getDeclaredField("clazz"));
+ FIELD_MEMBER_NAME_NAME = ReflectionKit.setAccessible(classMemberName.getDeclaredField("name"));
+ } catch (ClassNotFoundException | NoSuchFieldException e) {
+ throw new MybatisPlusException(e);
+ }
+ }
+
+ private final Class> clazz;
+ private final String name;
+
+ public IdeaProxyLambdaMeta(Proxy func) {
+ InvocationHandler handler = Proxy.getInvocationHandler(func);
+ try {
+ Object dmh = ReflectionKit.setAccessible(handler.getClass().getDeclaredField("val$target")).get(handler);
+ Object member = FIELD_MEMBER_NAME.get(dmh);
+ clazz = (Class>) FIELD_MEMBER_NAME_CLAZZ.get(member);
+ name = (String) FIELD_MEMBER_NAME_NAME.get(member);
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ throw new MybatisPlusException(e);
+ }
+ }
+
+ @Override
+ public String getImplMethodName() {
+ return name;
+ }
+
+ @Override
+ public Class> getInstantiatedClass() {
+ return clazz;
+ }
+
+ @Override
+ public String toString() {
+ return clazz.getSimpleName() + "::" + name;
+ }
+
+}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java
new file mode 100644
index 0000000..80295f7
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/LambdaMeta.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.yulichang.toolkit.support;
+
+/**
+ * Lambda 信息
+ *
+ * Created by hcl at 2021/5/14
+ */
+public interface LambdaMeta {
+
+ /**
+ * 获取 lambda 表达式实现方法的名称
+ *
+ * @return lambda 表达式对应的实现方法名称
+ */
+ String getImplMethodName();
+
+ /**
+ * 实例化该方法的类
+ *
+ * @return 返回对应的类名称
+ */
+ Class> getInstantiatedClass();
+
+}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java
new file mode 100644
index 0000000..11796f7
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ReflectLambdaMeta.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.yulichang.toolkit.support;
+
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.github.yulichang.toolkit.ClassUtils;
+import com.github.yulichang.toolkit.ReflectionKit;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.invoke.SerializedLambda;
+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 aClass = SerializedLambda.class;
+ 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;
+
+ public ReflectLambdaMeta(SerializedLambda lambda) {
+ this.lambda = lambda;
+ }
+
+ @Override
+ public String getImplMethodName() {
+ return lambda.getImplMethodName();
+ }
+
+ @Override
+ public Class> getInstantiatedClass() {
+ String instantiatedMethodType = lambda.getInstantiatedMethodType();
+ String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(StringPool.SEMICOLON)).replace(StringPool.SLASH, StringPool.DOT);
+ return ClassUtils.toClassConfident(instantiatedType, getCapturingClassClassLoader());
+ }
+
+ private ClassLoader getCapturingClassClassLoader() {
+ // 如果反射失败,使用默认的 classloader
+ if (FIELD_CAPTURING_CLASS == null) {
+ return null;
+ }
+ try {
+ return ((Class>) FIELD_CAPTURING_CLASS.get(lambda)).getClassLoader();
+ } catch (IllegalAccessException e) {
+ throw new MybatisPlusException(e);
+ }
+ }
+
+}
diff --git a/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java
similarity index 99%
rename from src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java
rename to mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java
index 1d4d96c..964cfc1 100644
--- a/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SelectColumn.java
@@ -9,7 +9,7 @@ import lombok.Getter;
* MPJLambdaWrapper 查询字段
*
* @author yulichang
- * @since 1.2.5
+ * @since 1.3.0
*/
@Getter
public class SelectColumn {
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java
new file mode 100644
index 0000000..4b7d4cb
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.yulichang.toolkit.support;
+
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+
+import java.io.*;
+
+/**
+ * 当前类是 {@link java.lang.invoke.SerializedLambda } 的一个镜像
+ *
+ * Create by hcl at 2020/7/17
+ */
+@SuppressWarnings("ALL")
+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;
+
+ public static SerializedLambda extract(Serializable serializable) {
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ oos.writeObject(serializable);
+ oos.flush();
+ try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())) {
+ @Override
+ protected Class> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ Class> clazz = super.resolveClass(desc);
+ return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
+ }
+
+ }) {
+ return (SerializedLambda) ois.readObject();
+ }
+ } catch (IOException | ClassNotFoundException e) {
+ throw new MybatisPlusException(e);
+ }
+ }
+
+ public String getInstantiatedMethodType() {
+ return instantiatedMethodType;
+ }
+
+ public Class> getCapturingClass() {
+ return capturingClass;
+ }
+
+ public String getImplMethodName() {
+ return implMethodName;
+ }
+}
diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java
new file mode 100644
index 0000000..d1a3ad4
--- /dev/null
+++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/support/ShadowLambdaMeta.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.yulichang.toolkit.support;
+
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.github.yulichang.toolkit.ClassUtils;
+
+/**
+ * 基于 {@link com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda} 创建的元信息
+ *