最近项目中使用mybatisplus 作为项目的orm,效率比mybatis提升了不少,用起来相当方便,其中通过lambda表达式取得字段名,特别方便
LambdaQueryWrapper<SpClips> where = new LambdaQueryWrapper<>();
where.in(SpClips::getClipId, ids);
这是怎么实现的呢,带着好奇心我们来分析一下这块的源码。
首先我们看下 AbstractLambdaWrapper 抽象类
protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
return getColumn(LambdaUtils.resolve(column), onlyColumn);
}
columnToString 函数将lambda表达式转换成字段名,
我们再看下 LambdaUtils.resolve(column) 这行代码处理的逻辑
/**
* 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。
* 该缓存可能会在任意不定的时间被清除
*
* @param func 需要解析的 lambda 对象
* @param <T> 类型,被调用的 Function 对象的目标类型
* @return 返回解析后的结果
* @see SerializedLambda#resolve(SFunction)
*/
public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
Class<?> clazz = func.getClass();
return Optional.ofNullable(FUNC_CACHE.get(clazz))
.map(WeakReference::get)
.orElseGet(() -> {
SerializedLambda lambda = SerializedLambda.resolve(func);
FUNC_CACHE.put(clazz, new WeakReference<>(lambda));
return lambda;
});
}
该段代码将lambda表达式转换成 SerializedLambda 对象,我们在来看看SerializedLambda 有哪些信息
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;
这里面有方法名信息,到目前为止,实现思路就比较清楚了,
初始化类:TableInfoHelper
核心类:LambdaUtils 、SerializedLambda
大家有兴趣可以深入看下这几个类的代码