【问题标题】:How do Spring repositories instantiate results from query methods?Spring 存储库如何实例化查询方法的结果?
【发布时间】:2021-10-19 11:22:02
【问题描述】:

假设以下 (jdbc) 存储库:

interface Repo : CrudRepository<MyType, Long> {
    @Query("select * from blabla")
    fun abc(): List<MyType>
}

对于 abc() 方法和父接口中包含的方法,Repo 接口的自动生成运行时实现知道如何将结果集序列化为 MyType 的实例,但受到某些限制。

Spring 如何在运行时访问泛型参数的类型信息?它如何仅根据接口中提供的类型信息来创建正确运行时类型的列表?

我的理解是,我不会从下面的mapV1() 之类的签名中获得足够的信息来实例化我的结果,因此我需要引入第二个类型为Class&lt;T&gt; 的参数,如mapV2() 所示:

class Mapper {
   fun <T> mapV1(source: Any): T {
       /* 
       try to instantiate a result 
       of type T reflectively
       */
   }
   fun <T> mapV2(source: Any, klass: Class<T>): T {
       /* 
       try to instantiate a result 
       of type T reflectively
       */
   }
}

Spring 以某种方式避免了这个问题。

【问题讨论】:

    标签: java kotlin generics reflection spring-data


    【解决方案1】:

    并非所有类型信息都被删除。方法的返回类型和参数类型、超类和超接口、字段类型等作为元数据存储在类文件中。 Java 反射 API 允许您获取它们:

    // note that the "as ParameterizedType" cast only succeeds if the type is generic
    println((Repo::class.java.genericInterfaces[0] as ParameterizedType)
        .actualTypeArguments.toList()) // [class MyType, class java.lang.Long]
    println((Repo::class.java.getDeclaredMethod("abc").genericReturnType as ParameterizedType)
        .actualTypeArguments.toList()) // [class MyType]
    

    您也可以使用 Kotlin 反射 API 执行此操作:

    println(Repo::class.supertypes[0].arguments) // [MyType, kotlin.Long]
    println(Repo::class.declaredMembers.find { it.name == "abc" }?.returnType?.arguments) // [MyType]
    

    但是,在mapV1 的情况下,您可以获得的唯一元数据只是“T”,这不是很有用。您无法获取调用者传递给它的参数。

    【讨论】:

    • 非常简洁的答案!非常感谢!
    • 我能否使用类似的技术来解析TmapV1() 的运行时类型?
    • @ErikMadsen 您仍然需要接受一个额外的参数,并且您将基本上从 Gson(或其他 Json 库)重新发明 TypeToken。我宁愿只使用Class,除非T 本身可以是泛型的,并且出于某种原因您还需要它的泛型类型。但只是为了实例化它? Class 就够了。至于为什么不添加新参数就不能这样做,我已经在编辑中解决了。
    • 查看 Gson 中的 TypeToken 是如何工作的 here
    猜你喜欢
    • 2018-08-09
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多