跳轉到內容

JavaBeans

75% developed
來自華夏公益教科書

導航 使用者介面 主題:v  d  e )


任何現代計算機語言的框架的核心都是可重用性。在重複的環境中使用以前構建的元件通常是可取的。在 快速應用程式開發 中,這些元件被證明更有幫助,因為您可以將它們從元件列表中拖出並在專案中的其他地方使用。這種級別的可重用性透過 JavaBeans 架構新增到 Java 程式語言中。

JavaBeans 是主流的 Java 元件模型,由 Sun Microsystems 於 1996 年推出。JavaBeans 的定義如下

“JavaBean 是一個可重用的軟體元件,可以在構建工具中以視覺化方式進行操作。”

Sun 與元件模型一起釋出了一個簡單的視覺化組合工具,即 BeanBox。它主要用於嘗試使用 Bean,而不是提供專業 IDE。對於實際應用,最好部署在支援 JavaBeans 視覺化組合的 Java IDE 中,例如 Visual Age 或 JBuilder。

正如我們將看到的,JavaBeans 本質上與標準 Java 類沒有區別,這使得元件模型非常易於使用。將 JavaBean 與普通 Java 類區分開的是 JavaBean 遵循 Oracle JavaBeans 標準(術語 JavaBean 或簡稱 bean 也指 JavaBean 類的例項)。為了便於重用,有一套功能和約定被採用

  • 存在無引數建構函式;
  • 支援永續性;
  • 透過 getter 和 setter 方法操作的屬性;
  • 支援內省;
  • 事件作為 bean 之間通訊的機制;
  • 支援透過屬性編輯器進行自定義。

JavaBeans 標準提供了一個框架,用於建立供 GUI 工具(包括 Java 開發環境)使用的物件。但在更常見的用法中,bean 是一個可序列化的類,它遵循 JavaBeans 的屬性命名約定。這些命名標準使使用 Java 內省 變得容易。

為了遵循這些標準,bean 需要一個或多個屬性抽象,它們表示物件的不同的狀態值。屬性有名稱(有效的 Java 識別符號)和型別(引用型別、基本型別或陣列型別)。預設情況下,JavaBean 類的屬性是透過存在 getter 方法、setter 方法或兩者來推斷的。

  • getter 方法用於從 bean 中獲取屬性的值。名稱通常是 getPropertyName 的形式。例如,String 屬性 whiskey 的 getter 方法是 public String getWhiskey()。對於布林屬性(型別為 boolean 的屬性),約定是使用命名模式 isPropertyName

isDiscounted() 將是名為 discounted 的布林屬性的 getter 方法。因此,大多數 getter 方法的簽名是 public PropertyType getPropertyName()public boolean isPropertyName()

  • setter 方法用於為 bean 的屬性賦值。setter 方法是 public void setPropertyName(PropertyType value) 形式的方法。對於前面的示例,setter 可以呼叫為 setWhiskey("bourbon");

根據 JavaBeans 標準,如上所述定義的 getter 和 setter 會自動確定類的屬性。但是,透過建立 java.beans.PropertyDescriptor 類,您可以透過顯式宣告每個屬性的屬性名稱以及 getter 和/或 setter 方法來指定備用實現。

屬性通常使用私有的例項變數來實現,但這不是必需的。

一個簡單的 JavaBean

[edit | edit source]

這是一個簡單的 JavaBean 型別示例,它具有屬性 int ageString color

Computer code 程式碼清單 9.12: Puppy.java
class Puppy implements java.io.Serializable {

  private static final long serialVersionUID = 348652158488L;

  private String color;

  private int age;

  public String getColor() {
    return color;
  }

  public void setColor(String color) {
    this.color = color;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

永續性

[edit | edit source]

物件成為 bean 的要求是定義一個公共的無引數建構函式,以便構建工具能夠以簡單的方式例項化 bean(在 Point bean 中,無引數建構函式是隱式給出的)。其次,需要實現 java.io.Serializablejava.io.Externalizable 介面之一。這些介面沒有規定任何方法的實現,但它們是一個認可,表明 bean 可以儲存到持久儲存中,如檔案或資料庫中。這樣,bean 可以在應用程式關閉或跨網路傳輸後恢復。將元件狀態儲存到持久儲存中的能力稱為永續性。Java 提供了一個標準序列化機制,它使序列化物件變得非常容易。或者,可以透過實現 Externalizable 介面以自定義方式儲存元件(例如,以 xml 格式)。

屬性

[edit | edit source]

bean 的屬性是所有透過公共方法訪問和修改的私有欄位。這些 getter 和 setter 方法應該按照一個簡單的命名約定來標記:對於某個名為 xxx 的屬性,應該有一個 getXxx() 來返回屬性值,還有一個 setXxx() 來設定屬性。

內省

[edit | edit source]

在 Java 和 J2EE 程式設計中,您只能在將物件強制轉換為宣告該方法的類或介面時呼叫物件上的方法。bean 屬性的結構化定義對於比較多個不應透過繼承相關聯的物件的單個公共屬性非常有用。

例如,一個程式可能包含一個表示公司員工的 bean,另一個包含公司佔用的建築物列表。編寫名為 listAssetNames() 的函式的程式設計師希望編寫一個簡單的方法來從多個 bean 中獲取“name”欄位,這些 bean 可以從 Employee 和 Building bean 中獲取該欄位,並且可以輕鬆地適應從其他可能尚未編寫的 bean 型別中獲取相同的欄位。

雖然這可以透過重寫 Employee 和 Building 使它們都繼承自名為 NamedObject 的一個類,或者透過建立一個 NamedObject 介面來完成,但兩種方法都有各自的問題。使用繼承是有限制的,因為每個子類只能從一個父類繼承,這限制了可以共享屬性的不同類的數量,以及可以共享的公共屬性的數量。此外,使用繼承來表達除簡單的“is-a”關係以外的關係可能會令人困惑,就像檢視數十個類定義以查詢單個“啞”getter 函式在何處實現一樣。建立介面解決了由多重繼承規則引起的問題,因為類可以使用任意數量的介面,但它仍然要求每個共享屬性都明確說明。

處理這種型別關係的最簡單、最優雅的方法是使用內省讀取 bean 屬性。jakarta 的 BeanUtils 包是處理需要以這種方式關聯的物件的常用方法,因為它利用了 JavaBean 命名約定的規律性。

Computer code 程式碼清單 9.13: 從 JavaBean 獲取屬性
public static Object getProperty(Object o, String propertyName) {
   if (o == null ||
       propertyName == null ||
       propertyName.length() < 1) {
      return null;
   }
   // Based on the property name build the getter method name
   String methodName = "get" +
                      propertyName.substring(0,1).toUpperCase() +
                      propertyName.substring(1);
   Object property = null;
   try {
      java.lang.Class c = o.getClass();
      java.lang.reflect.Method m = c.getMethod(methodName, null);
      property = m.invoke(o, null);
   } catch (NoSuchMethodException e) {
     // Handle exception
   }  catch (SecurityException e) {
     // No permission; Handle exception
   }
return property;
}

Computer code 程式碼清單 9.14: 使用 Apache Commons BeanUtils
import org.apache.commons.beanutils.PropertyUtils;

try {
  Object myValue = PropertyUtils.getSimpleProperty(o, propertyName);
} catch (IllegalAccessException e) {
  // Handle exception
} catch (InvocationTargetException e) {
  // Handle exception
} catch (NoSuchMethodException e) {
  // Handle exception
}

事件

[edit | edit source]

JavaBeans 透過事件相互互動。事件是元件可以通知其他元件的通知,表明發生了某些有趣的事情。例如,事件可能是按鈕上的滑鼠點選或視窗關閉。bean 可以是事件的源和目標。為了接收事件的通知,bean 必須在另一個 bean 上註冊為監聽器

Java 事件模型實現了觀察者設計模式,其效果是減少了元件間耦合。方法呼叫需要緊耦合,因為呼叫者和接收者需要在編譯時相互瞭解,而事件的所有通訊都僅透過介面進行。

一種特殊型別的事件是 PropertyChangeEvents。它們用於限制某些屬性只取特定值,例如,對於月份,整數值在 1 到 12 之間。每次修改此類繫結屬性時,都會將通知傳送給所有註冊的 PropertyChangeListeners

定製

[edit | edit source]

定製是透過屬性編輯器完成的。屬性編輯器是在設計時自定義特定屬性型別的工具。屬性編輯器是從所謂的屬性表中啟用的,屬性表顯示 bean 的所有屬性。如果選擇屬性進行自定義,屬性表會找出屬性的型別,並使用屬性的當前值顯示相應的屬性編輯器。

其他說明

[edit | edit source]

JavaBean 元件模型的一大優勢是它旨在簡化。開發 JavaBeans 非常簡單,因為預設情況下,Java 程式語言支援許多行為(如平臺獨立性或打包機制)。但是,可以選擇用額外的物件(如BeanInfos 或自定義的 PropertyEditors)來裝備 bean,以更靈活的方式使用元件模型。第二個便利是 Sun 根據 JavaBeans 元件模型設計了整個 Swing GUI 庫。因此,Swing 元件可以輕鬆地在視覺化構建工具中進行組合。

但是,JavaBeans 並沒有實現元件模型的所有功能。一個缺點是 JavaBeans 被限制在 Java 程式語言中,而元件的一個重要目標是實現語言的獨立性。

[edit | edit source]
  • 學習 JavaTM,Niemeyer,P. 和 Knudsen,J.,第 3 版,2005 年,O'Reilly:Sebastopol,CA。第 751-786 頁


華夏公益教科書