Mybatis-Plus读取Lambda字段方式

 ̄綄美尐妖づ 提交于 2020-02-26 09:07:50

第一步. 获取SerializedLambda

/**
* 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象
*
* @param lambda lambda对象
* @return 返回解析后的 SerializedLambda
*/
public static SerializedLambda resolve(SFunction<?, ?> lambda) {
	if (!lambda.getClass().isSynthetic()) {
		throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类");
	}
	try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
		@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 ExceptionUtils.mpe("This is impossible to happen", e);
	}
}

第二步.转换成SerializedLambda

/**
* 解析 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(() -> {
			// 调用Lambda转换方法转换成 Lambda 序列化对象
			SerializedLambda lambda = SerializedLambda.resolve(func);
			// 保存到缓存
			FUNC_CACHE.put(clazz, new WeakReference<>(lambda));
			return lambda;
		});
}

第三步.获取字段名称

/**
* 获取 SerializedLambda 对应的列信息,从 lambda 表达式中推测实体类
* <p>
* 如果获取不到列信息,那么本次条件组装将会失败
*
* @param lambda     lambda 表达式
* @param onlyColumn 如果是,结果: "name", 如果否: "name" as "name"
* @return 列
* @throws com.baomidou.mybatisplus.core.exceptions.MybatisPlusException 获取不到列信息时抛出异常
* @see SerializedLambda#getImplClass()
* @see SerializedLambda#getImplMethodName()
*/
private String getColumn(SerializedLambda lambda, boolean onlyColumn) throws MybatisPlusException {
	//获取方法名称并转换成字段名
	String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
	// mp进行一些操作, 不予深究, 最后返回字段名称
	Class<?> aClass = lambda.getInstantiatedType();
	if (!initColumnMap) {
		columnMap = LambdaUtils.getColumnMap(aClass);
	}
	Assert.notNull(columnMap, "can not find lambda cache for this entity [%s]", aClass.getName());
	ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));
	Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]",
				   fieldName, aClass.getName());
	return onlyColumn ? columnCache.getColumn() : columnCache.getColumnSelect();
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!