最近項目中使用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
大家有興趣可以深入看下這幾個類的代碼