JavaBeans 官方文档学习

提示,重点:JavaBeans的Property和 Events;PropertyEditor极其注册查找机制。



从目前来看,JavaBeans 更像是源自GUI的需求。

使用NetBeans新建一个Java Application,然后新建一个jFrame form,右边会有组件面板,如下:

这些组件,本质上都是bean!所以可被复用、可被引用、可被通知!

将任意一个组件拖进去安置,例如Button(按钮)。如下:

在右下角会显示该组件的属性,如下:

如果是英文版的NetBeans,你就会发现这里的属性就是Properties。你在这里进行的所有设置,如设置图标、字体、边框、背景等等操作,本质上都是调用相应的SETTER!(在SETTER之前会先调用PropertyEditor)

官方文档有这么一句:

A bean is a Java class with method names that follow the JavaBeans guidelines. A bean builder tool uses introspection to examine the bean class. Based on this inspection, the bean builder tool can figure out the bean‘s properties, methods, and events. -- 原文

类似Netbeans这样的builder tool,会识别并展示所有的property name and type,以及其他,以方便设计者在设计时进行操作。

JavaBeans’ property 中有两个特殊的:bound property、constrained property,如下:

bound property,当其值发生改变时,会通知监听器!两个含义:

1,该bean类包含两个方法:addPropertyChangeListener() and removePropertyChangeListener()

2,当值发生改变时,该bean会发送PropertyChangeEvent至注册过的监听器。

PropertyChangeEvent and PropertyChangeListener 都在 java.beans package中。

该包中还有一个类,PropertyChangeSupport,负责多数的bound properties工作。

代码示例如下:

import java.beans.*;

public class FaceBean {
    private int mMouthWidth = 90;
    private PropertyChangeSupport mPcs = new PropertyChangeSupport(this); // 这里

    public int getMouthWidth() {
        return mMouthWidth;
    }

    public void setMouthWidth(int mw) {
        int oldMouthWidth = mMouthWidth; //
        mMouthWidth = mw;
        mPcs.firePropertyChange("mouthWidth", oldMouthWidth, mw); // 这里
    }

    // 这里
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        mPcs.addPropertyChangeListener(listener);
    }

    // 这里
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        mPcs.removePropertyChangeListener(listener);
    }
}

constrained property,一种特殊的 bound property。bean会持续跟踪 a set of veto listeners。当constrained property 将要发生改变时,会先咨询监听器。任何一个veto listener都有机会否决这次改变,就是说,维持原值不变。

veto listeners独立于 property change listener。所幸, java.beans 包包含了一个 VetoableChangeSupport 类,可以极大的简化 constrained properties。

import java.beans.*;

public class FaceBean {
    private int mMouthWidth = 90;
    private PropertyChangeSupport mPcs = new PropertyChangeSupport(this);
    private VetoableChangeSupport mVcs = new VetoableChangeSupport(this); // 这里

    public int getMouthWidth() {
        return mMouthWidth;
    }

    public void setMouthWidth(int mw) throws PropertyVetoException {
        int oldMouthWidth = mMouthWidth;
        mVcs.fireVetoableChange("mouthWidth", oldMouthWidth, mw); // 这里
        mMouthWidth = mw;
        mPcs.firePropertyChange("mouthWidth", oldMouthWidth, mw);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        mPcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        mPcs.removePropertyChangeListener(listener);
    }
    // 这里
    public void addVetoableChangeListener(VetoableChangeListener listener) {
        mVcs.addVetoableChangeListener(listener);
    }

    // 这里
public void removeVetoableChangeListener(VetoableChangeListener listener) {
        mVcs.removeVetoableChangeListener(listener);
    }
}

JavaBeans’ method: A bean‘s methods are the things it can do. Any public method that is not part of a property definition is a bean method.

JavaBeans’ events: A bean class can fire off any type of event, including custom events.

和property一样,event也有自己的惯例:

public void add<Event>Listener(<Event>Listener a)

public void remove<Event>Listener(<Event>Listener a)

注意,listener必须是 java.util.EventListener 的子类。

类似NetBeans的builder tool可以识别 bean events。

使用BeanInfo

Beans,特别是图形组件,可能拥有大量的properties,难以快速的找到正确的properties进行编辑 -- 特别是对于新手来说。

BeanInfo可以改变bean在builder tool中的展示形式。Builder tool可以查询BeanInfo以找出哪些properties优先展示,哪些应该隐藏。

BeanInfo和bean的名字一样,但以 BeanInfo 结尾。例如,FaceBean与FaceBeanBeanInfo。

虽然可以手动创建BeanInfo,但是使用工具(如NetBeans)更简洁。

NetBeans中创建Bean的BeanInfo很简单,右键 - BeanInfo Editor… 即可。第一次会提示创建,同意即可。

默认进入源码编辑界面,记得切入设计界面。如下:

可以针对property进行选择,主要就是是否优先展示、是否隐藏、是否bound property、是否constrained property。

builder tool在发现一个bean类之后,会自动查找同路径下的BeanInfo,以决定如何展示bean。

--------------------------

JavaBeans入门很简单,但这货其实是很有深度的。现在来看点高级货,包括 如何持久化保存一个bean、如何为定制的类型提供定制的editor。

Bean Persistence (持久化)

想了下,这个也是源自GUI吧,总不能每次打开的界面都是最原始的界面。

The mechanism that makes persistence possible is called serialization. Object serialization means converting an object into a data stream and writing it to storage. Any applet, application, or tool that uses that bean can then "reconstitute" it by deserialization. The object is then restored to its original state.

囧了,居然是序列化和反序列化。

All beans must persist. To persist, your beans must support serialization by implementing either the java.io.Serializable (in the API reference documentation) interface, or the java.io.Externalizable (in the API reference documentation) interface. These interfaces offer you the choices of automatic serialization and customized serialization.

原来有两个接口,涨姿势了。

实现 Serializable的bean,可以自动序列化/反序列化,会自动忽略transient和static的字段。

The Java Object Serialization API automatically serializes most fields of a Serializable object to the storage stream. This includes primitive types, arrays,and strings. The API does not serialize or deserialize fields that are marked transient or static.

你可以控制你的bean的序列化level!三种途径:

    • 自动序列化,实现Serializable接口即可。序列化整个对象,除了transient 和 static 字段。
    • 定制序列化。将不想序列化的自动使用transient 或 static 修饰。— 囧。
    • 定制文件格式,实现 Externalizable和其两个方法。Bean会被以那种文件格式写入。

默认序列化:Serializable接口,就是一个标记,告诉JVM希望进行默认序列化。有几个关键点需要知道:

类必须有一个针对父类无参构造的访问。

如果父类实现了Serializable接口,子类可以继承。

会忽略transient 和 static。 -- 各种重复啊

选择性序列化:writeObject 和 readObject

如果你的serializable class含有下面两个方法中的任意一个,默认的序列化就不会发生:

private void writeObject(java.io.ObjectOutputStream out) throws IOException;

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

通过这两个方法,你可以控制如何序列化/反序列化。

Externalizable接口

完全控制bean的序列化/反序列化(例如,以一种特定文件格式进行读写)。

需要实现两个方法:writeExternal和readExternal。

实现类必须有一个无参构造。

Long Term Persistence 长期持久化

Long-term persistence is a model that enables beans to be saved in XML format.

居然只支持XML格式。

Encoder 和 Decoder

XMLEncoder类用于输出Serializable对象。例如:

XMLEncoder encoder = new XMLEncoder(
           new BufferedOutputStream(
           new FileOutputStream("Beanarchive.xml")));

encoder.writeObject(object);
encoder.close();

XMLDecoder类读取XMLEncoder创建的XML:

XMLDecoder decoder = new XMLDecoder(
    new BufferedInputStream(
    new FileInputStream("Beanarchive.xml")));

Object object = decoder.readObject();
decoder.close();

下面是SimpleBean的XML形式:

<?xml version="1.0" encoding="UTF-8" ?>
<java>
  <object class="javax.swing.JFrame">
    <void method="add">
      <object class="java.awt.BorderLayout" field="CENTER"/>
      <object class="SimpleBean"/>
    </void>
    <void property="defaultCloseOperation">
      <object class="javax.swing.WindowConstants" field="DISPOSE_ON_CLOSE"/>
    </void>
    <void method="pack"/>
    <void property="visible">
      <boolean>true</boolean>
    </void>
  </object>
</java>

Bean Customization 定制

修改一个bean的appearance和behaviour,两种方式:

  • 通过一个property editor。
  • 通过customizer。 同property editor的区别是,customizer关联到bean,property editor关联到property。

PropertyEditor

这里的属性设值,都是调用了相应的PropertyEditor!-- 因为你输入的都是字符串啦。

例如,点击 toolTipText 后面的【…】,就会打开一个StringEditor window:

PropertyEditorSupport提供PropertyEditor接口的空实现,继承它,按需覆盖方法即可完成自己的PropertyEditor。

Property Editors 是如何关联到 Properties 的? (重点)

  • 通过一个BeanInfo对象 显式的关联。
  • 通过java.beans.PropertyEditorManager.registerEditor方法 显式的注册。
  • 名字查找。如果一个类没有显式的关联PropertyEditor,那 PropertyEditorManager 会按以下顺序搜索其editor:

同包路径下以类的名字开始,以’Editor’结束。

在classpath中搜索(以类的名字开始,以’Editor’结束)!

Customizers (可以忽略)

在bean层次上configure或edit一个bean。

所有的customizer 必须:

  • 继承 java.awt.Component 或其子类。
  • 实现 java.beans.Customizer 接口。就是实现注册 PropertyChangeListener对象的方法。
  • 默认构造。
  • 通过BeanInfo.getBeanDescriptor将customizer关联到目标类。

参考文档:

The Java™ Tutorials,Trail: JavaBeans(TM)

时间: 2024-11-08 19:08:26

JavaBeans 官方文档学习的相关文章

Spring 4 官方文档学习(十二)View技术

1.介绍 Spring 有很多优越的地方,其中一个就是将view技术与MVC框架的其他部分相隔离.例如,在JSP存在的情况下使用Groovy Markup Templates 还是使用Thymeleaf,仅仅是一个配置问题. 本章覆盖了主要的view技术,嗯嗯,可以与Spring结合的那些,并简明的说明了如何增加新的view技术. 本章假定你已经熟悉了Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图 -- 它覆盖了views如何耦合到MVC框架

Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图

接前面的Spring 4 官方文档学习(十一)Web MVC 框架,那篇太长,故另起一篇. 针对web应用的所有的MVC框架,都会提供一种呈现views的方式.Spring提供了view resolvers,可以让你在浏览器中render model,而不必绑定到某种特定的view技术上.开箱即用,例如,Spring可以让你使用JSPs.Velocity目标和XSLT views.See Chapter 23, View technologies for a discussion of how

根据ThinkPHP官方文档学习opensns框架

根据ThinkPHP官方文档学习opensns框架 1.解读Application下各个Controller文件夹下的作用 控制器类的命名方式是:控制器名(驼峰法,首字母大写)+Controller 控制器文件的命名方式是:类名+class.php(类文件后缀) namespace Weibo\Controller; ///这是系统的规范要求,表示当前类是weibo模块下的控制器类,与实际路径一致 use Think\Controller; //引入 Think\Controller 类库便于直

React官方文档学习记录(四)- 条件渲染

一点点记录,建议需要学习React的移步官方文档去学习. 在React中,你可以创建一个清晰(distinct)的组件来简要描述你现在需要的东西.然后,你只需要使用你应用中的state来渲染它们. React中的条件型渲染跟JavaScript中的条件运算符运行方式差不多.好像就是使用JavaScript中的if或者三元运算符创建元素来显示现在的状态,然后让React更新UI来匹配这些修改. 下面这个例子就是根据不同的isLoggedIn进行不同的欢迎. 1 2 3 4 5 6 7 8 9 10

Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

在前面的文档中讲解了Spring MVC的特殊beans,以及DispatcherServlet使用的默认实现.在本部分,你会学习两种额外的方式来配置Spring MVC.分别是:MVC Java config 和  MVC XML namespace. 原文: Section 22.2.1, "Special Bean Types In the WebApplicationContext" and Section 22.2.2, "Default DispatcherSer

Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的人,但事实并非如此,例如我.好在闷着头看了一遍,又查资料又敲代码,总算明白了. 其实说穿了一文不值,我们用一个例子来解释: 假定,现有一个app,功能是接收你输入的生日,然后显示你的年龄.看起来app只要用当前日期减去你输入的日期就是年龄,应该很简单对吧?可惜事实不是这样的. 这里面有三个问题: 问题一:我们输入的永远是字符串,字符串需要转成日期格式才能被我们的ap

Spring 4 官方文档学习 Spring与Java EE技术的集成

本部分覆盖了一下内容: Chapter 28, Remoting and web services using Spring -- 使用Spring进行远程和web服务 Chapter 29, Enterprise JavaBeans (EJB) integration -- EJB集成 Chapter 30, JMS (Java Message Service) -- JMS (Java 消息服务) Chapter 31, JMX Chapter 32, JCA CCI Chapter 33,

Python3.5.2官方文档学习备忘录

网址:https://docs.python.org/3/ 虽然学习官方文档有些耗时,不过看最原版的还是感觉好一点,原汁原味没有曲解没有省略. 从命令行向Python传递参数,运行:python - abc def import sys sys.argv 在命令行下的显示结果:['-','abc','def'] 在命令行中运行python,_ 变量会保存上一次运行的结果 >>> tax = 12.5 / 100 >>> price = 100.50 >>&g

Spring 4 官方文档学习(五)核心技术之SpEL

1.介绍 SpEL支持在runtime 查询.操作对象图. 2.功能概览 英文 中文 Literal expressions 字面值表达式 Boolean and relational operators 布尔和关系操作符 Regular expressions  正则表达式 Class expressions 类表达式 Accessing properties, arrays, lists, maps 访问properties.arrays.lists.maps Method invocati