史上最惊艳的 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)、GemfireMongoDBNeo4

幸运的是,如果您在 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 的编程模型,同时保留了特定于存储的功能和特性。

在存储库方面,这个熟悉且一致的编程模型的一个关键特性是使用注解来配置持久对象映射。这个想法最初是在 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 公共库提供了 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 社区中所有即将举行的活动。

查看全部