有史以来最惊人的 Java 类型声明

工程 | David Turanski | 2012 年 8 月 3 日 | ...

我想我应该对 Java 和泛型相当熟悉,但最近我遇到了这段 Java 代码,它让我停下了脚步。

public abstract class AnnotationBasedPersistentProperty<P extends PersistentProperty<P>> extends AbstractPersistentProperty<P> {..}

这个类是 Spring Data 框架的 Repository 支持的内部组件,它消除了实现数据访问层时编写样板代码的需要,并为映射域对象和管理到任何类型持久存储的数据访问提供了通用的编程模型。Spring Data 当前的存储库实现包括关系数据库(JPA)、GemfireMongoDBNeo4j

幸运的是,如果你在 Java 应用程序中使用 Spring Data,你将永远不会看到这段代码。它隐藏在 Spring Data 简洁而强大的 Repository 抽象之后,提供了查询、分页、排序和常见的 CRUD 操作。例如:


public class SomeClient {
    @Autowired
    private PersonRepository repository;
    public void doSomething() {
        List<Person> persons = repository.findByLastname("Matthews");
    }
}

正如 Spring Data 项目的使命宣言中所述:
Spring Data 在提供 NoSQL 和关系型存储的熟悉且一致的基于 Spring 的编程模型的同时,保留了特定于存储的功能和能力。

当涉及到 repository 时,这个熟悉且一致的编程模型的一个关键特性是使用注解来配置持久化对象映射。这个想法最初是在 Hibernate 中实现的,随后被 JPA 所采纳。保留特定于存储的功能要求核心框架提供一些通用注解,例如 @Id@Transient,同时也支持特定于存储的注解。

为了支持映射域对象的属性,Spring Data Repository 的实现应该继承 AnnotationBasedPersistentProperty。这个类提供了跨持久化存储的通用注解处理逻辑,并提供了用于特定存储的自定义注解处理的钩子。碰巧的是,这个类继承了另一个名为 AbstractPersistentProperty 的抽象类,声明如下:

public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>> implements PersistentProperty<P>

AbstractPersistentProperty 自然地实现了 PersistentProperty 接口。所以在我们深入研究之前,让我们先看看 PersistentProperty 接口的声明:

public interface PersistentProperty<P extends PersistentProperty<P>>

哇——我的脑子里充斥着鸡和蛋、汉诺塔和 哥德尔、埃舍尔和巴赫 的画面!这个递归的精妙之处在于,核心的 PersistentProperty 接口需要一个扩展它的类型。换句话说,形式参数 P 代表 PersistentProperty 的一个子类型,它由特定于存储的实现来定义。特定于存储的 PersistentProperty 类型是对象映射策略的核心,并且通过 Spring Data 的一些通用接口(包括 PersistentProperty 本身)暴露出来。例如,PersistentProperty 声明了以下方法: PersistentEntity<?, P> getOwner(); PersistentEntity 是持久化域对象类的抽象表示。它旨在解决类级别的映射问题,并包含对——请注意——持久化属性的引用。PersistentEntity 被强类型化为扩展的 PersistentProperty 接口,并且还暴露了这里由通配符?形式参数表示的域类类型。

所以让我们再看看最初的类型声明:

public abstract class AnnotationBasedPersistentProperty<P extends PersistentProperty<P>> extends AbstractPersistentProperty<P> {..}

到目前为止,其含义应该很清楚了:Spring Data commons 库提供了 AbstractPersistentProperty,它实现了 PersistentProperty 来管理所有底层的字段和类型信息。AnnotationBasedPersistentProperty 继承了这个类,以添加注解支持。所有这些类型都需要一个扩展 PersistentProperty 的类型参数。这方面的一些例子:

public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty>{...}

public interface GemfirePersistentProperty extends PersistentProperty<GemfirePersistentProperty>{...}

最终,所有这些参数化类型实际上是一种优雅的方式,允许实现 Spring Data Repository 的人使用该框架来暴露特定于存储的功能,而无需诉诸类型转换、instanceof 等。事实上,已经有许多实现正在进行中,这证明了该框架的强大功能。在撰写本文时,所有 Spring Data 项目都已作为里程碑版本发布。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有