帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程 >
定制你的Java--根据应用剪裁JavaBeans
作者:未知 发布时间:2005-03-12 来源:JSP天空网
摘 要: 对 于 可 定 制 的 组 件(Components), 开 发 者 可 以 根 据 自 己 的 需 要 剪 裁。 可 定 制 的JavaBeans 中 有 应 用 程 序 开 发 者 可 以 修 改 的 属 性(Properties) ─ ─ 例 如, 改 变Beans 的 外 观 和/ 或 动 作。 本 文 将 介 绍 如 何 定 制JavaBeans。 我 们 将 讨 论 属 性、 读 取 器(getter) 和 设 置 器(setter) 方 法(Mothods), 绑 定(Bound) 和 约 束(Constrained) 属 性, 以 及 使 定 制 简 单 化 的 设 计 模 板(Design Pattern)。 然 后 介 绍 属 性 编 辑 器(Editors) 和 定 制 器(Customizers), 最 后 我 们 在 一 个 已 有 的JavaBeans 中 增 加 定 制 功 能。

可 定 制 的 组 件 有 更 大 的 应 用 范 围。 例 如, 对 于 一 个 电 子 表 格(Spreadsheets) Bean, 假 如 它 必 须 占 满 全 屏 幕、 与 你 的 应 用 程 序 颜 色 方 案 冲 突 或 者 只 能 以16 进 制 方 式 显 示 数 据, 不 管 它 在 其 他 方 面 的 功 能 有 多 出 色, 你 恐 怕 不 能 用 它。

JavaBeans 规 范 对 简 单 情 况 提 供 了 非 常 简 单 的 识 别、 修 改 属 性 的 特 征, 对 复 杂 的 情 况 提 供 了 扩 展。

本 文 将 研 究JavaBeans 的 定 制 接 口、 组 件 属 性、 以 及 如 何 编 写 你 的Beans 使 得 集 成 开 发 环 境(IDEs) 可 以 将 这 些 属 性 显 示 给 应 用 程 序 开 发 者。 我 们 还 将 讨 论 以 下 的 问 题: 绑 定 和 约 束 属 性, 它 们 可 以 方 便Beans 之 间 通 信 和 维 持 一 致 性; 定 制 器, 它 可 以 使 我 们 更 方 便 地 定 制;BeanBox 的 使 用, 它 是Sun 免 费 提 供 的JavaBeans 测 试 工 具。

什 么 是 定 制
软 件 组 件 是 通 用 的 功 能 和 数 据 模 块, 它 可 以 在 很 多 情 况 下 使 用, 软 件 组 件 的 定 制 是 很 重 要 的, 如 果 应 用 程 序 开 发 者 可 以 控 制 其 外 观 和 行 为, 它 才 能 在 很 多 应 用 程 序 中 得 到 应 用。 例 如, 如 果 一 个 按 钮 类 的 文 本 标 签 总 是“Button”, 与 之 相 关 的 动 作 总 是 重 启 计 算 机( 虽 然 在 一 些 操 作 系 统 中 这 可 能 是 最 有 用 的 工 具 之 一) 的 话, 那 它 是 没 有 多 大 用 处 的。

简 单 的 组 件, 如 按 钮 都 有 很 多 开 发 者 可 以 控 制 的 属 性, 其 中 包 括:

是 否 使 能

动 作

背 景 颜 色

文 本 颜 色

大 小

位 置

形 状

标 签 文 本

当 按 此 按 钮 时 播 放 的 声 音 文 件
复 杂 的 组 件 需 要 更 多 的 定 制。 定 制 一 个 远 程 数 据 库 连 接 可 能 从 可 用 的 服 务 器 列 表 中 进 行 选 择( 信 息 只 有 在 运 行 时 才 可 用)、 选 择 协 议( 同 上)、 指 定 用 户 名 和 密 码 和 设 置 通 过 防 火 墙 访 问。

Beans 的 属 性
一 般 说 来, 定 制 就 是 配 置Beans 的 内 部 状 态, 使 其 外 观 和 行 为 适 合 所 用 的 环 境。 这 些 内 部 状 态( 颜 色、 大 小 和 密 码 字 符 串 等) 在JavaBeans 规 范 里 称 为 属 性。Beans 中 的 属 性 可 以 用 称 为 访 问 器(Accessors) 的 方 法 读 取 和 修 改。 一 个 访 问 器 方 法 是 读 取 属 性 值 的getter 方 法, 或 者 是 修 改 属 性 值 的setter 方 法。 在 按 钮Beans 中 有String getLabel() 方 法, 它 返 回Beans 的 当 前 标 签, 有void setLabel(String newLabel) 方 法, 它 设 置Beans 的 当 前 标 签, 只 有getter 方 法 的 属 性 是 只 读 的。

为 什 么 不 简 单 地 访 问Beans 内 部 地 数 据 成 员, 直 接 读 取 和 修 改 它 们, 而 是 编 写 一 些 访 问 器 呢 ? 因 为 不 能 保 证 属 性 和Beans 内 部 的 成 员 数 据 直 接 对 应。 例 如,Beans 中 的 标 签 属 性 可 能 是 一 个AWT 标 签 对 象, 但 是 也 可 能 不 是。 标 签 文 本 可 能 来 自 数 据 库, 可 能 是 另 一 个Bean 的 标 签, 也 可 能 当 需 要 时 形 成 一 个 标 签。 访 问 器 方 法 是Beans 中 属 性 的 统 一 接 口, 它 隐 藏 了 属 性 的 实 现 细 节。 这 是 好 的 面 向 对 象 编 程 惯 例, 因 为 它 减 小 了 对 象 间 的 依 赖 和“ 耦 合”。

符 合JavaBeans 规 范 的 集 成 开 发 环 境 能 分 析Beans, 找 到 它 的 属 性, 同 时 它 还 能 给 每 种 属 性 创 建 直 观 的 显 示( 称 为 属 性 编 辑 器), 允 许 开 发 者 在 设 计 时 修 改 属 性。 当 开 发 者 将 一 个Bean 放 入 应 用 程 序 中 时, 集 成 开 发 环 境 在 面 板 上 画 出 此Bean, 然 后 显 示 属 性 表, 它 是Bean 所 有 属 性 的 简 单 列 表, 每 个 属 性 有 一 个 对 应 的 编 辑 器。 集 成 开 发 环 境 调 用 所 有 的getter 方 法, 将Bean 中 当 前 属 性 值 显 示 在 属 性 表。 当 开 发 者 修 改 属 性 表 中 的 属 性 时, 集 成 开 发 环 境 调 用 相 应 的setter 方 法, 更 新 所 选Bean 中 的 相 关 属 性。

对 低 等 到 中 等 复 杂 度 的Beans, 在 设 计 时 调 用setter 方 法 配 置 它 往 往 已 经 足 够。 为 了 支 持 复 杂Beans 更 高 程 度 的 定 制, 规 范 中 定 义 了 定 制 器(customizer) 类。 开 发 者 可 以 扩 充Beans, 这 就 为 实 现 任 何 类 型 的 定 制 打 开 了 方 便 之 门: 复 杂 的 颜 色 拾 取 器、 图 形 化 的 网 络 配 置 精 灵, 只 要 你 愿 意, 甚 至 可 以 编 写 一 个VRML 界 面。 实 际 上, 以 上 描 述 的 属 性 表 可 以 看 作 是 集 成 开 发 环 境 自 动 产 生 的 定 制 器。 这 种 模 式 在JavaBeans 框 架 中 是 常 见 的: 简 单 的 情 况( 在 这 种 情 况 下, 简 单 的 属 性 类 型 已 有 属 性 编 辑 器) 往 往 只 须 很 少 或 根 本 不 须 工 作, 但 是 其 中 隐 藏 着 对 复 杂 情 况 的 访 问 方 法。

如 何 使Beans 可 定 制
JavaBeans 框 架 使 创 建 有 可 定 制 属 性 的Beans 变 得 相 当 容 易。 大 部 分 情 况 下, 根 本 无 须 写 任 何 代 码。 这 是 因 为JavaBeans 规 范 定 义 了 命 名 约 定, 集 成 开 发 环 境 可 用 它 来 推 断 与 属 性 相 关 的 方 法。 规 范 中 将 这 种 约 定 称 作 设 计 模 板。 如 果 不 考 虑 语 义 原 则 的 话 则 很 简 单: 名 字、 返 回 值 和 参 数 类 型 决 定 了 属 性 的 名 字 和 类 型。 当 集 成 开 发 环 境 装 载Beans 时, 使 用JDK 1.1 reflection 机 制 检 查Beans 中 所 有 的 方 法, 寻 找 以get 和set 开 头 的 方 法, 然 后 将 属 性 加 入 到 属 性 表 中, 以 便 开 发 者 定 制Beans。

定 制Beans
我 们 可 以 看 一 个 具 体Bean 定 制 的 例 子: 扩 展 一 个 简 单 的BarChart Bean。 读 源 程 序 便 可 以 发 现:BarChart Bean 已 经 有 符 合 规 范 中 设 计 模 板 的 读 取 器 和 设 置 器 方 法 ─ ─void setPercent(int iPercent) 和int getPercent()。 换 句 话 说, 它 已 经 有 一 个 属 性:percent。 将BarChart Bean 装 载 入BeanBox 中 看 有 什 么 发 生。


图1 BeanBox 中 的Barchat

图 的 左 边 是 一 个 包 括 可 用Beans 的 面 板, 便 于 在BeanBox 中 放 置。 中 部 是BeanBox 本 身,BarChart 已 被 选 择, 而 右 边 是BarChart 的 属 性 列 表。 属 性 列 表 中 包 括 五 个 属 性: 前 景 和 背 景(Color 类 型)、 字 体(Font 类 型)、percent( 整 数) 和 名 字( 字 符 串)。 当BeanBox 装 载BarChart 时, 发 现int getPercent 和void setPercent(int iPercent) 方 法, 便 将percent 看 作 是Bean 的 一 个 属 性, 并 将 它 以 及 一 个 整 型 数 属 性 编 辑 器(percent 标 签 右 边 的 文 本 框) 加 入 到 属 性 表 中。 调 用getPercent() 函 数 填 充 属 性 编 辑 器 的 值( 本 例 中 值 为0)。 对 属 性 表 中 的 所 有 属 性 都 做 同 样 的 处 理。

BarChart 只 定 义 了percent 属 性, 那 其 它 属 性 是 从 哪 里 来 的 呢 ? 因 为BarChart 定 义 为:
public class BarChart extends Canvas implements Serializable。

BarChart 继 承 了java.awt.Canvas, 而 它 又 继 承 了java.awt.Component, 它 定 义 了Color getForeground(),void setForeground(Color) 等。 这 意 味 着, 如 果 你 定 义 一 个Bean 的 子 类, 你 便 巧 妙 地 得 到 一 个 包 括 父Bean 所 有 属 性 的 新Bean。

当 你 在BeanBox 的 属 性 表 中 修 改 属 性 时,Bean 马 上 就 被 更 新。 在percent 的 属 性 编 辑 器 中 输 入"62",BeanBox 便 做 出 相 应 的 反 应, 如 图2 所 示。


图2 62% 的BarChart

集 成 开 发 环 境( 本 例 为BeanBox), 检 测 到percent 属 性 编 辑 器 的 值 改 变, 便 调 用setPercent() 更 新BarChart 的percent。

如 果 你 的 应 用 程 序 正 好 需 要 一 个 蓝 色 背 景、 两 点 的 黑 色 边 框 和 对 选 择 百 分 比 填 充 红 色,25 乘150 的BarChart, 一 切 都 很 好。

好 在 我 们 有 此Bean 的 源 代 码, 我 们 可 以 增 加 一 些 新 属 性:Color 型fillColor、floodColor 和borderColor, 整 型borderWidth、barHeight 和barWidth。 作 为 例 子, 我 们 增 加floodColor() 访 问 器。 我 们 首 先 定 义 填 充 颜 色private Color fgColor_ = Color.red。 为 了 避 免 与java.awt.Component 的 前 景 和 背 景 属 性 相 混 淆, 我 们 更 名 为floodColor, 并 编 写 它 的 访 问 器:

private Color floodColor_ = Color.red;
public void setFloodColor(Color floodColor)
{
   floodColor_ = floodColor;
}

public Color getFloodColor()
{
   return floodColor_;
}

对 其 他 属 性 也 可 增 加 类 似 的 访 问 器, 这 就 形 成 了 一 个 灵 活 的 新Bean 的 新 类 文 件。

到 此,BarChart 就 是 可 定 制 的 了。 我 们 可 以 将 它 们 设 置 成 我 们 喜 欢 的 外 观, 如 图3 所 示。


图3 已 定 制 的BarChartBeans

我 们 可 以 看 到 四 个BarChart Beans, 每 个 用 不 同 的 颜 色 方 案 和 不 同 的 百 分 比 填 充 定 制。 对BarChart 类 增 加 了 几 个 方 法 便 可 给 应 用 程 序 开 发 者 提 供 极 大 的 灵 活 性。

当 属 性 的 类 型 是 内 建 的 类 型, 而 且 你 并 不 介 意 键 入 字 符 串 来 提 取 颜 色, 这 样 工 作 得 很 好。 但 是 当 属 性 的 类 型 为 自 定 义 类 型 时, 例 如BarChart 有direction 属 性 指 示BarChart 的 增 长 方 向, 合 理 的 值 为 上、 下、 左 和 右, 如 何 定 制 呢 ?

笨 的 方 法 是 让 用 户 键 入 整 数0-3 来 指 示 方 向。 在JavaBeans 规 范 中 明 智 的 方 法 是 编 写 自 己 的 属 性 编 辑 器。java.beans.PropertyEditor 接 口 和java.beans.PropertyEditorSupport 实 用 工 具 类 允 许Beans 开 发 者 对 于 以 上 描 述 的 自 定 义 类 型, 如 方 向 类 型 指 定 属 性 编 辑 器。 自 定 义 属 性 编 辑 器 甚 至 可 以 是 图 形 化 的:NetworkConfiguration Bean 可 能 有HostConnections 属 性, 它 可 以 用 鼠 标 在 服 务 器 之 间 画 出 连 接 的 方 式 来 配 置。

对 于 基 本 的 属 性 有 最 后 一 点 需 要 注 意。 有 的 属 性 可 能 定 义 为 值 的 数 组, 而 不 仅 仅 是 标 量, 这 些 属 性 就 是 索 引 属 性(Indexed Properties)。 它 与 标 量 属 性 相 比 在 访 问 器 方 法 方 面 是 不 同 的。 读 取 器 和 设 置 器 方 法 被 重 载。 可 以 以 单 个 元 素 的 方 式 访 问 属 性:

void setProperty(int index, TYPE value)
TYPE getProperty(int index)

或 者 一 次 整 个 数 组 的 方 式:

void setProperty(TYPE valueList[])
TYPE[] getProperty()

例 如 对 于Polygon3D Bean, 它 将 自 己 画 在 画 布(Canvas) 上, 可 以 单 独 地 访 问 它 的 点:

Point3D newPoint = new Point3D(0,25,0);
myPolygon.setPoint(2,newPoint); //Throws exception if <3 points
或 者 一 次 设 置 整 个 数 组:

Point3D p1 = new Point3D(0, 10, 0);
Point3D p2 = new Point3D(10, 1, 15);
Point3D p3 = new Point3D(15, 0, 25);
Point3D[] points = {p1, p2, p3};
myPolygon.setPoint(points);

绑 定 和 约 束 属 性
绑 定 和 约 束 让 人 听 起 来 感 到 痛 苦, 但 是 它 能 将 你 从 诸 如 当 一 个 属 性 改 变 时 更 新 相 关 的GUI 元 素 等 繁 杂 的 细 节 里 解 脱 出 来 轻 松 地 工 作。 同 时 它 还 能 帮 助 你 维 护Beans 之 间 的 一 致 性。 绑 定 属 性 是 一 种Bean 属 性, 当 它 的 值 改 变 时, 它 的 设 置 器 方 法 通 知 其 它 对 象( 称 为 监 听 器listeners), 使 其 它Beans 可 以 执 行 一 定 的 动 作。 约 束 属 性 与 绑 定 属 性 相 似, 除 了 监 听 器 可 以“ 否 决” 属 性 的 改 变。 为 了 理 解 如 何 使 用 这 种 属 性, 有 必 要 理 解 新 的JDK 1.1 的 事 件 处 理 结 构 的 基 本 原 理。

事 件 监 听 器
当 属 性 改 变 时,Java 组 件 用JDK 1.1 中 出 现 的 新 概 念, 事 件 监 听 器(Event Listeners) 接 口 通 知 其 它 组 件。 当 属 性 改 变 时, 其 对 象 创 建 一 个 包 括 属 性 信 息 的 事 件 对 象(Event Objects), 然 后 传 给 对 此 属 性 感 兴 趣 的 组 件。

在AWT 旧 的 事 件 模 型 中, 事 件 处 理 基 于 继 承: 为 了 捕 获 一 个 事 件 并 作 出 处 理, 你 必 须 建 立 一 个 已 经 处 理 这 个 事 件 的 父 类 的 子 类, 改 变 其 行 为。 这 使 得 难 于 创 建、 处 理 新 的 事 件 类 型。 事 件 监 听 器 方 法 基 于 事 件 集 中 处 理: 产 生 事 件 的 对 象 维 护 一 张 其 它 对 这 类 事 件 感 兴 趣 的 对 象 的 列 表, 当 事 件 发 生 时, 将 事 件 传 给 这 些 对 象。

事 件 监 听 器( 概 念 性) 的 例 子
我 们 举 参 议 员 的 例 子。


图4 事 件 监 听 器 示 例

在 图4 中, 考 虑 四 个 对 象( 记 者、 战 略 家、 助 手 和 狂 热 者), 他 们 都 想 知 道 参 议 员 的 薪 水 变 动( 薪 水 是 参 议 员 类 的 一 个 属 性)。 假 设 法 律 规 定, 参 议 员 对 感 兴 趣 的 人 必 须 通 知 其 薪 水 的 变 动。 参 议 员 提 供 一 个 事 件 监 听 器 注 册 方 法, 本 例 为void addSalaryListener(SalaryListener l)。 调 用 此 方 法 的 对 象 被 加 入 到 参 议 员 为 薪 水 变 动 事 件 而 维 护 的 监 听 器 列 表 中。 当 薪 水 变 动 时, 调 用setSalary() 方 法, 它 同 时 创 建 一 个 包 括 薪 水 变 动 量 的SalaryChangedEvent 对 象, 调 用 监 听 器 的void salaryChanged(SalaryChangedEvent event) 方 法 将 此 事 件 传 给 监 听 器。 对 此 事 件, 各 监 听 器 完 成 各 自 特 定 的 功 能。

薪 水 实 际 的 变 动 量 包 含 在 参 议 员 传 给 各 监 听 器 的SalaryChangedEvent 对 象 中, 我 们 可 以 从java.util.EventObject 创 建 包 含 参 议 员 薪 水 变 动 量 的 子 类:

//Encapsulates salary change
public class SalaryChangedEvent extends java.util.EventObject
{
double raiseAmount_;
void setRaiseAmount(double raiseAmount){
raiseAmount_ = raiseAmount;

}

// tc

}

下 面 我 们 定 义SalaryListener 接 口, 它 扩 展java.util.EventListener 处 理SalaryChangedEvent:

interface SalaryChangedListener extends java.util.EventListener
{
   void SalaryChanged(SalaryChangedEvent event);
}

以 下 所 有 的 类 可 以 实 现SalaryListener 接 口, 使 自 己 注 册 到 参 议 员 类 并 接 收SalaryChangedEvent。

class Crank extends Crackpot implements SalaryListener
{
//register interest in salary by adding self to senator&acute;s
//list of salary listeners
public void Crank(Senator senatorToHarass) {
//place myself on this senator&acute;s list of listeners.
senatorToHarass.addSalaryChangedListener(this);
}

//the senator calls this method when his/her salary property changes
public void SalaryChanged(SalaryChangedEvent event) {
double theRaise = event.getRaiseAmount();
//Ramble ad naueam
}
}

绑 定 属 性
理 解 事 件 监 听 器 后, 我 们 讨 论 如 何 应 用 到 绑 定 属 性 上。 在java.beans 中 定 义 了PropertyChangeListener 事 件 监 听 器 和PropertyChangeEvent 事 件 类 型, 处 理 绑 定 属 性 的 改 变 通 知。Bean 是 事 件 的 来 源( 参 议 员), 监 听 器 是 所 有 对 属 性( 薪 水) 感 兴 趣 的 对 象。 对 事 件 来 源 的 绑 定 属 性 感 兴 趣 的 对 象 实 现PropertyChangeListener 接 口, 因 而 成 为 监 听 器。PropertyChangeEvent 来 源 的 对 象( 例 如 参 议 员) 实 现 以 下 方 法:

void addPropertyChangeListener(PropertyChangeListener l)
void removePropertyChangeListener(PropertyChangeListener l)

因 而 使 此 属 性 变 成 绑 定 的。 所 有 绑 定 属 性( 如 薪 水) 的 设 置 器 方 法 负 责 创 建PropertyChangeEvent, 并 在 属 性 改 变 以 后 将 它 传 给 所 有 的 注 册 监 听 器。 这 是 比 参 议 员 例 子 中 更 常 用 的 方 案, 因 为 只 有 一 种PropertyChangeEvent 类 型, 而 不 是 每 个 特 定 的 属 性 都 有 一 种 类 型。

为 了 更 容 易 实 现,JavaSoft 开 发 组 一 个 线 程 安 全(thread-safe) 的 类, 叫 做java.beans.PropertyChangeSupport, 它 管 理PropertyChangeListeners 列 表, 并 负 责 传 送 事 件。 你 可 以 将PropertyChangeSupport 作 为 一 个 成 员 包 括 在 你 的 类 中, 然 后 在 你 的 设 置 器 方 法 中 使 用 它, 处 理 所 有 的 绑 定 属 性 改 变 的 通 知。

约 束 属 性
除 了(1) 属 性 在 通 知 所 有 监 听 器 之 后, 而 不 是 之 前 改 变,(2) 设 置 器 方 法 可 以 抛 出 一 个PropertyVetoException 异 常 来 否 决 建 议 的 改 变 以 外, 约 束 属 性 和 绑 定 属 性 是 完 全 一 样 的。 事 件 的 来 源 对 象 将PropertyChangeEvent 传 给 所 有 监 听 器, 通 知 它 们 对 属 性 建 议 的 改 变。 如 果 一 个 监 听 器 不 同 意 这 个 改 变, 它 抛 出 一 个PropertyVetoException 异 常, 这 样 事 件 来 源 对 象 便 不 改 变 属 性。 在 这 种 情 况 下, 设 置 器 方 法 稍 微 不 同:

void setProperty(TYPE property) throws PropertyVetoException

因 此, 约 束 属 性 的 接 口 是VetoableChangeListener, 而 不 是PropertyChangeListener。 使 处 理 更 容 易 的 支 持 类 是VetoableChangeSupport。

当 一 个 监 听 器 否 决 一 个 改 变 时, 会 引 起 另 一 个 问 题: 一 部 分 监 听 器 认 为 属 性 值 已 经 改 变( 因 为propertyChanged() 方 法 已 经 被 调 用), 而 另 一 本 分 则 认 为 没 有 改 变。 因 此, 此 时 设 置 器 方 法 必 须 回 过 头 来 重 新 通 知 所 有 已 被 通 知 的 监 听 器, 对 象 没 有 改 变 属 性 值。 一 般 说 来, 设 置 器 方 法 并 不 负 责 这 种“ 改 变 - 回 头” 通 知 否 决,VetoableChangeSupport 工 具 类 为 你 处 理 这 些 工 作, 除 非 有 十 分 充 分 的 理 由 自 己 去 实 现 它 以 外, 应 该 使 用VetoableChangeSupport。

约 束 属 性 的 例 子
为 了 使BarChart 类 更 智 能 化, 我 们 将Barchart Bean 的percent 属 性 与 另 外 一 个Bean 的 整 数 属 性 绑 定。percent 可 以 绑 定 到 任 何Beans 中 的 任 何 属 性 上, 只 要 它 能 传 送 包 含 整 数 的PropertyChangeEvent( 假 设 此 整 数 在0 和100 之 间),BarChart 就 会 忠 实 地 用 图 形 方 式 将 此 数 显 示 出 来。

首 先 我 们 必 须 将BarChart 类 设 计 成 事 件 监 听 器, 只 有 当 它 是 一 个PropertyChangeListener, 即 实 现java.beans.PropertyChangeListener 接 口, 才 能 接 收 到PropertyChangeEvent。 为 实 现 此 接 口, 一 个 类 只 用 实 现 一 个 方 法:public void propertyChange(PropertyChangeEvent event)。 事 件 来 源 对 象 改 变 属 性 时, 它 同 时 产 生PropertyChangeEvent, 并 且 传 给 所 有 的 监 听 器。PropertyChangeEvent 对 象 包 含 了 发 送 它 的 对 象 的 如 下 信 息: 被 改 变 属 性 的 名 字、 其 新 值 和 旧 值 以 及 以 什 么 对 象 存 储( 即 整 数 必 须 以Integer 对 象 存 储 等 等)。

为 了 使BarChart 成 为 一 个PropertyChangeListener, 我 们 加 入 一 个 接 口 并 且 实 现 它:

public class BarChartBean
   extends Canvas implements Serializable, PropertyChangeListener
{
   // Respond to a property change event for the property
   //"value" by updating my value to new value
   public void propertyChange(PropertyChangeEvent event)
   {
       Integer newValue = (Integer)event.getNewValue();
       setPercent(newValue.intValue());
   }
}

只 要 当BarChartBean 接 收 到 一 个PropertyChangeEvent, 便 读 取 其 新 值 并 且 赋 值 给percent 属 性。

我 们 需 要 一 个 给BarChart Bean 传 送 事 件 的 类。 以 下 创 建 一 个 称 为IntBox 的 简 单Bean, 它 是java.awt.TextField 的 子 类, 只 接 收 数 字 并 计 算 它 的 值。IntBox 有 一 个 特 点: 它 实 现 了 两 个 称 为public void addPropertyChangeListener(PropertyChangeListener listener) 和public void removePropertyChangeListener(PropertyChangeListener listener) 的 函 数。 实 现 了PropertyChangeListener 接 口 的 类( 例 如BarChart) 便 可 以 调 用 这 些 函 数, 将 自 己 加 入 或 者 移 出 监 听 来 自IntBox 的PropertyChangeEvents 的 类 的 列 表。 以 下 是 这 些 方 法 的 实 现:

public class IntBox extends TextField implements Serializable
{
   PropertyChangeSupport pcs_;    //constructor, etc
   //Allow other objects to register interest in my bound properties
   public void addPropertyChangeListener(PropertyChangeListener listener)
   {
       pcs_.addPropertyChangeListener(listener);
   }
   //Allow other objects to remove their interest in my bound properties
   public void removePropertyChangeListener(PropertyChangeListener listener
   {
       pcs_.removePropertyChangeListener(listener);
   }

实 用 工 具 类PropertyChangeSupport 为 你 维 护 列 表, 从 而 简 化 了 对 监 听 器 的 跟 踪。 当IntBox 的value 属 性 改 变 时( 即 当setValue() 被 调 用 时), 必 须 通 知 所 有 的 监 听 器。 我 们 在setValue() 中 加 入 额 外 的 一 行 来 创 建 和 传 送 事 件 对 象:

//Set new vaule
public void setValue(int value)
{
   int oldValue = prev_;
   setText(Integer.toString(value));
   int newValue = getValue();

   pcs_.firePropertyChange("value", new Integer(oldValue),
new Integer(newValue));
   prev_=newValue;
}

这 段 代 码 是 相 当 简 单 的, 我 们 读 取 新 值 后 调 用PropertyChangeSupport 对 象 中 的firePropertyChange() 方 法, 并 给 出 改 变 属 性 的 名 字、 旧 值 和 新 值。 然 后 跟 踪 旧 值 以 便 下 次 调 用 时 再 次 使 用 它。firePropertyChange() 方 法 创 建 一 个PropertyChangeEvent 对 象 并 且 将 它 传 给 所 有 的 监 听 器, 除 非 旧 值 和 新 值 相 等。PropertyChangeEvent 中 嵌 入 了 源 对 象 和 属 性 名, 以 便 监 听 器 根 据 谁 改 变 了 什 么 来 决 定 如 何 动 作。

合 二 为 一
我 创 建 了 一 个 称 为ColorBar 的 类, 它 包 括IntBox Bean 和BarChart Bean。 将 它 装 载 入BeanBox 便 可 以 看 到 它 的 动 作。ColorBar 在 其 构 造 器 中 创 建 了IntBox 和BarChart 组 件, 然 后 执 行:

intBox_.addPropertyChangeListener(barChartBean_);

这 是 关 键 之 处。BarChartBean 成 了 一 个PropertyChangeListener, 当IntBox 的 值 改 变 时, 它 便 是 监 听 器 中 的 一 员。 事 件 的 顺 序 很 简 单:

用 户 键 入 数 字 并 敲 回 车。

IntBox.processKeyEvent() 从 中 获 取 当 前 整 数 值 并 且 调 用setValue()。

IntBox.setValue() 更 新 属 性 值, 然 后 调 用firePropertyChange()。

firePropertyChange() 创 建PropertyChangeEvent 对 象 并 且 传 给BarChartBean 的propertyChanged()。

BarChartBean.propertyChanged() 设 置BarChartBean 的percent 值,BarChart 被 更 新。( 假 设 输 入 的 数 在0 到100 之 间)
在BeanBox 中 的 结 果 如 图5 所 示。


图5 绑 定 属 性 工 作 正 常

这 里 有 一 个 问 题:BarChart 只 接 收0 到100 之 间 的 输 入, 但 是IntBox 可 以 将 其value 属 性 设 置 为 任 意 的 正 整 数。 这 个 问 题 可 以 用 前 面 讨 论 过 的 约 束 属 性 解 决。 如 果BarChart 实 现VetoableChangeListener, 而IntBox 使 用VetoableChangeSupport 对 象, 则 当 值 超 出 范 围 时,BarChart 可 以 在propertyChanged() 中 抛 出 一 个 异 常,IntBox 便 被 禁 止 将 新 值 赋 值 给value。 只 有BarChart 接 受 的 数 才 是 允 许 的。

结 论
关 于 属 性 主 题 还 有 很 多 值 得 讨 论。 特 别 是, 因 为BeanBox 支 持PropertyChangeListener 接 口, 它 能 自 动 形 成 类, 将 一 个Bean 的 属 性 绑 定 到 另 一 个Bean 的 属 性 上。 你 可 以 试 试: 在BeanBox 中 装 入 一 个BarChartBean 和 一 个IntBox, 选 择IntBox, 然 后 在 菜 单 上 选 择Edit->Bind Property, 你 将 发 现 你 可 以 以 图 形 的 方 式 创 建ColorBar Bean。

以 上 我 们 讨 论 了 属 性 以 及 如 何 利 用 它 定 制Beans。 我 们 讨 论 了 事 件 监 听 器 接 口、 绑 定 属 性 和 约 束 属 性, 然 后 用PropertyChangeListener 接 口 将 一 个Bean 的 属 性 绑 定 到 另 一 个 的 属 性 上。
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
无相关信息

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·放眼未来 帝国近期将有重大举措!
·PHPWind6.3.2版通行证发布
·帝国备份王2008版正式发布
·帝国备份王2008版发布
·phpcms2007转帝国CMS5.0程序发布
·dedecms5.1转帝国CMS5.0程序发布
·帝国网站管理系统V5.0商业购买说明
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统