有史以来最令人惊叹的 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 的编程模型,同时保留了特定于存储的功能和特性。

当涉及到存储库时,这个熟悉且一致的编程模型的关键特性是使用注解来配置持久对象映射。这个想法首先在 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 是持久化域对象的类的抽象表示。它旨在解决类级别的映射问题,并包含对 - 等等 - Persistent 属性的引用。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 社区中所有即将举行的活动。

查看全部