Tuesday, December 11, 2012

Apache Commons --- Betwixt

说起 beans 一直都比较陌生,为了好好了解一下 Java 自己的哲学,于是趁研究 Betwixt 的时候学习了一下 Java beans 到底是什么东西,简单的说 beans 是符合以下要求的 Java class,
  • default constructible,即可以默认构造,但这个并不保证对应的 bean 处于 valid 状态
  • 所有的“属性”都含有 getter/setter 方法,这两个方法必须满足前者返回对应类型不带参数,后者带一个参数返回 void
  • 实现了 java.io.Serializable,这包括 readObject、writeObject 和 readObjectNoData 三个方法
复杂的说... 那可以参看这个 100+ 页的文档。很多 Java 的库会要求操作的对象满足一些 Java beans 的要求,前面了解的 beanutils 就会要求满足第二点。bean 的这些要求看起来非常的“机械”,这主要是为了实现某些 framework,比如 IDE 等,不过这种要求如果不做任何简化强加在 Java 程序员身上,那就是一种悲哀了,所以不少 IDE 还是支持自动生成这些 boilerplates 的。另外需要说明的是 beans 如果需要在 GUI 开发中使用,往往还会支持 event,这是类似 signal/slot 或者说 observer pattern。

正因为以上原因,beans 其实与某个 java package 是独立的,但是处理 beans 需要的一些手段被抽象出来,SDK 里面提供了 java.beans 这个 package,其中很多接口就能看出来主要是为了让这些 beans 与 IDE 等 framework 更好工作,比如
  • BeanInfo 获得 bean 的一些 property 等信息,Customizer 用来为 bean 某些信息进行更新
  • DesignMode 用来判断是否在设计界面(如 applet 的设计),PropertyEditor 用来帮助编辑属性

当然 java.beans 提供的一些支持还比较接近底层,特别是和 IDE 打交道的部分,同时里面还提供了两个类跟这里 Betwixt 有关,那就是 XMLDecoder 和 XMLEncoder,两者负责将一个 bean 写到 XML 文件里面或者从里面构造出一个 bean。Betwixt 的目标就是将这个转换过程变成可以控制的,通过尽量少的代价干涉定制者得到需要的效果。直接用 XMLEncoder 的话大致如下
import java.beans.XMLEncoder ;

public class TestBeanCodec {
    private int age ;

    public int getAge () {
        return age ;
    }

    public void setAge (int a) {
        age = a ;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void main (String[] args) {
        TestBeanCodec bean = new TestBeanCodec () ;
        bean.setAge (5) ;
        bean.setName ("foo") ;

        XMLEncoder encoder = new XMLEncoder (System.out) ;
        encoder.writeObject (bean) ;
        encoder.close () ;
    }
}
使用 betwixt 的话我们为每个 class 提供一个 class.betwixt 文件打包到 jar 里面,之后使用 org.apache.commons.betwixt 里面的 BeanWriter/BeanReader 就能进行定制化的输入输出了。

参看 userguideAPI例子

No comments:

Post a Comment