JavaBeans v1.0
我的上一篇博客研究了当前JavaBeans(TM)规范的内容。 关键特征元素可以总结如下:
- 属性--使用getter和setter方法访问
- 事件--属性的变化事件
- 方法--所有的公共方法
- BeanInfo - 允许自定义属性、事件和方法
- 豆--一个访问功能的实用类
- 属性编辑器--一个编辑属性的机制,包括转换为字符串格式或从字符串格式转换。
- GUI支持--允许对Bean进行视觉操作
这些功能很适合1997年,因为最初的目标是成为一个组件系统,与其他类似的系统如COM/DCOM进行互操作。 这些功能不再是我们所需要的了,所以任何Beans v2.0自然会有很大的不同。
Beans v2.0--数据抽象
Beans v2.0规范的关键目标是定义对象中数据的抽象。
当这种抽象存在时,框架和库的编写和交互就会变得简单得多。 例如,一个最基本的序列化框架只需要遍历对象图中的所有Bean和属性,就可以完成其任务。
除了框架之外,许多临时的编码任务也变得简单了,因为在bean和属性的对象图上行走要容易得多。 例如,从一个任意的bean开始,在对象图中找到一个特定类型的所有实例。
数据抽象必须是完全往返的。 规范必须允许将数据从Bean读成另一种格式。 但它也必须提供工具,允许从先前读取的数据重新创建原始Bean。
Bean v2.0 - Mutable vs Immutable
JavaBean v1.0规范隐含地定义了可变的对象。 它要求所有Bean都有一个没有args的构造函数,因此属性被填充的唯一方法就是使用设置器。 这种可变性是人们对JavaBean的主要抱怨之一,而且通常是对Java本身的抱怨。
任何Bean v2.0规范都必须支持不可变的对象
不可变类现在是系统的一种常见设计方法,而且越来越受欢迎。 因此,支持它们对于涵盖当今使用的各种数据对象至关重要。
任何Bean v2.0规范都必须支持可变对象。 虽然有些人对任何可变性嗤之以鼻,但对于一个应用程序来说,这仍然是一个完全有效的选择。在可变和不可变的数据对象之间做决定是一种权衡。 Beans v2.0规范需要支持这两种选择。
支持不可变的意义在于,需要有一个替代无参数构造器和公共设置器的方法来支持构造。 这很可能是某种 "Bean builder"。
Bean v2.0 - Bean和属性
术语 "Bean "通常与一个特定的Java类相关,如Person 。术语 "Property "通常与该类的一个字段相关,如surname 或forename 。
任何Bean v2.0规范都不能对Bean和属性有一个基于反射的看法
首先,属性与字段(实例变量)不同。 字段持有对象的状态,但不一定是对象希望公开的形式(例如,它可能以优化的格式存储)。 因此,Bean必须能够控制它所公布的属性集。
其次,我们希望Bean有一个动态的属性集,这可能包括一个有固定的基本属性集和一个可扩展的附加属性图的Bean,或者一个完全动态的Bean,更接近于许多动态语言的数据模型。
这就意味着Bean和Class 之间没有一对一的映射,属性和java.lang.reflect.Field 之间也没有一对一的映射。
JavaBeans v1.0规范以一种特殊的方式处理索引属性。 我看不出有什么理由要在Beans v2.0中这样做,尤其是考虑到现在使用的集合类型的范围。
Beans v2.0 - 获取器和设置器
目前的JavaBeans v1.0规范要求getter和setter都要有一个物理的java.lang.reflect.Method。Beans v2.0需要提供的是一种抽象,因为它提供了更多的选择。
任何Beans v2.0规范都不能要求通过java.lang.reflect.Method 来访问数据
摒弃直接暴露反射的做法提高了抽象水平,它允许替代的对象设计被暴露为 bean。
例如,考虑一个没有公开的getters和setters的Bean,通过Bean v2.0的抽象,它仍然可以将其数据以属性的形式暴露出来,提供与框架的互操作性,但对于大多数程序性使用来说,则是将数据封装起来。 这解决了JavaBean的另一个大的批评,即它们导致状态被暴露而不是隐藏。
另一个例子是基于HashMap 的Bean。在这种情况下,每个属性都不存在Method ,只是通过名称来获取。能够将其暴露为Bean,就能提供所需的动态行为。
这样做的意义在于,Bean v2.0规范的抽象将仅仅是Map 接口get 和put 的长线。
Beans v2.0 - 注释
目前的JavaBeans v1.0规范早于Java中的注解。 但现在注解是Java中许多编程实践的关键。
任何Bean v2.0规范都必须提供对属性和Bean注释的访问
注释是由Annotation 接口的实现来表示的。恰好,Annotation 接口不是反射的一部分。自己实现一个注释是可能的(除了编译器警告之外)。
现在需要的是Beans v2.0规范的抽象提供对Bean注释集的访问,以及对每个属性的注释集的访问,而不需要通过反射。 有了这一步,以及上面的步骤,许多直接使用反射的情况将完全消失,Beans v2.0的抽象已经足够好了。
Beans v2.0 - 事件
当前的JavaBeans v1.0规范认为事件是抽象的第一类部分。
在Beans v2.0规范中,没有很好的理由包括事件
目前的JavaBeans v1.0规范是以GUI为重点的,因此事件是必不可少的元素。 但这里概述的Beans v2.0规范关注的是一个不同的目标,即对对象中的数据进行抽象。 将数据从Bean到另一种格式再回到Bean,并不需要事件或GUI。
现在会有一些人伸手去拿评论框,要求必须包括事件。 但仔细想想,你应该意识到你不需要。
这里为Beans v2.0提出的任何建议都没有夺走今天在JavaBeans v1.0中有效的东西。GUI开发者仍然可以继续使用今天的getters、setters和事件,包括绑定和约束的属性。java.beans 包将继续存在并继续可用。此外,JavaFX是Java GUI的发展方向,它对属性有自己的方法。
Beans v2.0 - 转换为/从字符串
目前的JavaBeans v1.0规范包括PropertyEditor 。该类的一个用例,特别是在Spring框架中,是将一个简单的对象(通常是VALJO)转换成字符串。例如,这包括Integer 、Enum 、Class 和Currency 。
任何Beans v2.0规范都必须解决简单类型向/从字符串的转换
Beans v2.0规范最常见的用例是迭代对象图并以某种方式处理它,比如写出JSON或XML消息。 为了使之实用,对象图中的所有对象要么是Bean,要么是可转换为字符串的简单类型。 因此,非常需要简单类型的字符串转换来完善该规范。
Joda-Convert项目包含了一套简单的接口和类来解决这个问题,我想任何Beans v2.0规范的解决方案都是类似的。
Beans v2.0 - 但Bean实际上是什么样子的呢?
Beans v2.0的部分目标是允许不同类型的Bean:不可变的和可变的;私有的getters和setters和公有的;基于动态地图的结构和基于字段的结构。
任何Bean v2.0规范都不应该过度限制Bean的实现方式
我们知道Oracle目前还没有在语言层面上的属性计划。 因此,Beans v2.0规范对类的设计方式规定一个单一的方法也是没有意义的。 相反,该规范的目的是让那些以不同方式设计的类都能认同一种与框架和库交互的共同方式,而不需要getters、setters和no-args构造器。
Joda-Beans、Lombok、Immutables和Auto项目(以及其他许多项目)都提供了不同的方式来创建Bean,而无需编写手工代码。所有这些都可以适应拟议的Bean v2.0规范,像Jackson、Hibernate、Dozer和Groovy(仅举几例)这样的框架也可以。
简单的答案是,Bean可以像现在一样有getters和setters。 真正的答案是,只要能通过Beans v2.0的API暴露其数据,Bean可以以任何方式出现。
总结
目前的JavaBeans v1.0规范已经非常陈旧,对我们今天构建的各种应用来说并不那么有用。 这篇博客概述了我对Beans v2.0规范应采取何种方向的看法:
- 专注于数据抽象
- 支持可变和不可变的豆子
- 完全从反射中抽象出来
- 对getters和setters没有要求
- 不要求无args构造函数
- 支持动态可扩展的属性
- 访问Bean和属性注释
- 简单类型与字符串之间的转换
- 没有对事件的支持