通过Function获取bean的属性名称

文章解释了TkMapper框架中自定义Fn接口以及使用writeReplace方法获取Lambda表达式的属性名称的过程。它涉及到Java序列化机制中的SerializedLambda类,该类存储Lambda表达式的信息,用于在反序列化时重构Lambda。
摘要由CSDN通过智能技术生成

在使用tkmapper的example时候,我们经常会写如下代码:

    @Override
    public JobDefinitionsEntity queryJobDefinitionByAppIdAndName(Integer appId, String name) {
        Weekend<JobDefinitionsEntity> weekend = new Weekend<>(JobDefinitionsEntity.class);
        weekend.weekendCriteria().andEqualTo(JobDefinitionsEntity::getAppId, String.valueOf(appId))
            .andEqualTo(JobDefinitionsEntity::getName, name);
        return jobDefinitionsMapper.selectOneByExample(weekend);
    }

很好奇,

`weekend.weekendCriteria().andEqualTo(JobDefinitionsEntity::getAppId, appId) 这个是如何通过Function获取到appId这个属性名称的.

查看tkmapper源码可以看到源码如下:

    public WeekendCriteria<A, B> andEqualTo(Fn<A, B> fn, Object value) {
        super.andEqualTo(Reflections.fnToFieldName(fn), value);
        return this;
    }

`Reflections.fnToFieldName` 核心是这个方法

    public static String fnToFieldName(Fn fn) {
        try {
            Method method = fn.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);
            String getter = serializedLambda.getImplMethodName();
            if (GET_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(3);
            } else if (IS_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(2);
            }
            return Introspector.decapitalize(getter);
        } catch (ReflectiveOperationException e) {
            throw new ReflectionOperationException(e);
        }
    }

其中Fn定义为:

public interface Fn<T, R> extends Function<T, R>, Serializable {
}    

看到这里会有以下几个疑问点

  1. 为什么tkmapper要自己再定义一个Fn extends Function ?能不能直接使用Function

  1. Method method = fn.getClass().getDeclaredMethod("writeReplace"); 这个`writeReplace` 又是什么鬼

  1. SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn); 的SerializedLambda又是什么

下面将一一回答

首先是问题1,它的答案其实和问题2有关系

writeReplace 是 Java 序列化机制中的一个方法,用于在序列化对象时返回一个代理对象,以便在反序列化对象时恢复原始对象。它的定义如下:

private Object writeReplace() throws ObjectStreamException;

在 Reflections.fnToFieldName 方法中,fn 参数是一个函数式接口,它实现了 Serializable 接口。因此,可以使用 writeReplace 方法来获取序列化后的 Lambda 表达式。

这样问题1和问题2就解答了

问题3:

SerializedLambda 是 Java 8 引入的一个类,它用于存储序列化后的 Lambda 表达式的信息,以便在反序列化时重新构建 Lambda 表达式。

具体来说,当一个 Lambda 表达式被序列化时,它的信息会被存储在一个 SerializedLambda 对象中。SerializedLambda 类实现了 Serializable 接口,因此可以被序列化和反序列化。在反序列化时,SerializedLambda 对象会被用来构建 Lambda 表达式的实例。

SerializedLambda 类包含了 Lambda 表达式的信息,例如:

  • capturingClass:表示 Lambda 表达式所在的类;

  • functionalInterfaceClass:表示 Lambda 表达式实现的函数式接口的类型;

  • functionalInterfaceMethodName:表示函数式接口中唯一的抽象方法的名称;

  • functionalInterfaceMethodSignature:表示函数式接口中唯一的抽象方法的签名;

  • implClass:表示 Lambda 表达式实现的类;

  • implMethodName:表示 Lambda 表达式实现的方法的名称;

  • implMethodSignature:表示 Lambda 表达式实现的方法的签名;

  • instantiatedMethodType:表示 Lambda 表达式实例的方法类型。

通过这些信息,SerializedLambda 类可以在反序列化时重新构建 Lambda 表达式的实例,并调用相应的方法。

SerializedLambda 类一般不需要我们手动使用,它通常是在反序列化 Lambda 表达式时由 Java 序列化机制自动使用。在 Reflections.fnToFieldName 方法中,SerializedLambda 类被用来从序列化后的 Lambda 表达式中获取方法名称。具体来说,serializedLambda.getImplMethodName() 方法可以获取 Lambda 表达式实现的方法的名称,这个名称就是从中提取方法名称的关键。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值