声明: 内容参考自Java核心卷卷II第8版

1. Why Beans?
可重用组件,可视化编程。

 

2. The Bean-Writing Process。JavaBean 无需继承某个类。你可以提供一些属性供用户修改,
也可以提供监听事件供用户处理。

 

3. Using Beans to Build an Application
你需要将的JavaBean打包成一个jar文件。首先你需要提供一个manifest文件来说明你的
JavaBean,形如:

Manifest-Version: 1.0
Name: com/horstmann/corejava/ImageViewerBean.class
Java-Bean: TrueName: com/horstmann/corejava/FileNameBean.class
Java-Bean: True

说明:
a、在Manifest-Version与第一个Name段之间必须有一个空行;
b、你通过Name来指定你的JavaBean类文件,通过Java-Bean: True来指定这是一个JavaBean;
c、在第二个JavaBean说明与第一个JavaBean说明之间也必须有一个空行;
d、该manifest文件必须以一个空行结束。
     
接下来通过Jar命令打包你的JavaBean:
jar cvfm ImageViewerBean.jar ImageViewerBean.mf com/horstmann/corejava/*.class。
接着,在NetBeans等IDE中,通过添加组件的方式来将你的JavaBean集成到可视化开发环境中,
你就可以通过拖拽的方式来使用的可视化JavaBean啦。

 

4. Naming Patterns for Bean Properties and Events。
a、public Type getPropertyName()
     public void setPropertyName(Type newValue)
   此时你的属性名为propertyName(将方法的get/set去掉,然后将第一个字母转为小写)
b、public boolean isPropertyName()
     public void setPropertyName(boolean b)
   对于boolean类型的属性,使用isPropertyName来替代getPropertyName;然而getPropertyName
   也可以,但是推荐使用isPropertyName。此时,属性名也是propertyName。
c、如果方法去掉set/get后得到的“PropertyName”串的前两个字母都是大写格式的,则映射
   属性名时,不将第一个字母转为小写,而直接使用PropertyName。(如:getURL())
d、如果你的JavaBean中包含添加或删除事件监听器的方法,那么Bean Builder将会认为你的
   JavaBean会产生事件。该事件类必须以Event结尾且继承EventObject类,如果该类不继承
   EventObject类,在编译时并不会报错,因为EventObject类并不是必须的,然而你的JavaBean
   将无法对事件做出响应。

public void addEventNameListener(EventNameListener e)
public void removeEventNameListener(EventNameListener e)
public EventNameListener[] getEventNameListeners()

5. Bean Property Types。
a、Simple Properties。(单值属性)
提供如下方法来设置/获取属性值.

public void setFileName(String f)
{
 ...
}public String getFileName()
{
 ...
}


b、Indexed Properties。(数组属性)
提供如下方法来设置/获取属性值.

public String[] getExtensions() { return extensions; }
public void setExtensions(String[] newValue) { extensions = newValue; }
public String getExtensions(int i)
{
   if (0 <= i && i < extensions.length) return extensions[i];
   else return "";
}
public void setExtensions(int i, String newValue)
{
   if (0 <= i && i < extensions.length) extensions[i] = value;
}private String[] extensions;


c、Bound Properties。(捆绑属性)
捆绑属性的两个要求:
I. 如果属性值变了,bean必须发送一个PropertyChange事件给所有注册的监听者。
II.为了使监听者能够注册到bean,bean必须实现如下两个方法:
void addPropertyChangeListener(PropertyChangeListener listener)
void removePropertyChangeListener(PropertyChangeListener listener)
同时建议也实现下面的这个方法:
PropertyChangeListener[] getPropertyChangeListeners()
但是,如果你的JavaBean直接或者间接地继承自Component类,则不需要实现上述的方法。
你只需在属性更改以后通过调用firePropertyChange("propertyName", oldValue, newValue);
即可,但是数组属性更改通知是不受支持的。
如果你的类不是继承自Component类,对于上述的add/remove/get三个方法的实现,你可以借助于
java.beans包中的PropertyChangeSupport类来简化实现过程,示例如下:

private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener)
{
   changeSupport.addPropertyChangeListener(listener);
}public void removePropertyChangeListener(PropertyChangeListener listener)
{
   changeSupport.removePropertyChangeListener(listener);
}public PropertyChangeListener[] getPropertyChangeListeners()
{
   return changeSupport.getPropertyChangeListeners();
}


对于数组属性,你需要调用:
changeSupport.fireIndexedPropertyChange("propertyName", index, oldValue, newValue);
d、Constrained Properties(受限属性)
受限属性的更改必须在所有监听者都没有投否决票的情况下才能生效,否则值将不会改变。
对于一个受限属性,你的JavaBean需要提供以下两个方法:

public void addVetoableChangeListener(VetoableChangeListener listener);
public void removeVetoableChangeListener(VetoableChangeListener listener);


同时建议提供另外一个方法:
public VetoableChangeListener[] getVetoableChangeListeners();
你可以像捆绑属性一样借助于VetoableChangeSupport来实现上面的方法:

private VetoableChangeSupport vetoSupport = new VetoableChangeSupport(this);
public void addVetoableChangeListener(VetoableChangeListener listener)
{
   vetoSupport.addVetoableChangeListener(listener);
}
public void removeVetoableChangeListener(VetoableChangeListener listener)
{
   vetoSupport.removeVetoableChangeListener(listener);
}


为了更新一个受限属性的值,你需要参考如下步骤:
I. 通知所有的Vetoable Change Listeners来intent to(个人理解是检测该属性的新值是否合法)
改变该属性的值,通过如下方法:
vetoSupport.fireVetoableChange("value",oldValue,newValue);
II.如果所有的Vetoable Change Listeners都没有抛出PropertyVetoException,那就更新该属性
的值。
III.通知注册到属性的Property Change Listener。
示例实现如下:

public void setValue(Type newValue) throws PropertyVetoException
{
   Type oldValue = getValue();
   vetoSupport.fireVetoableChange("value", oldValue, newValue);
   // survived, therefore no veto
   value = newValue;
   changeSupport.firePropertyChange("value", oldValue, newValue);
}


如果你的JavaBean直接或间接地继承自JComponet,则你可以不必借助于VetoableChangeSupport
类,而可以直接使用JComponent类提供的同名方法。
注意:你不可以为一个直接或间接继承自JComponent类的JavaBean的单独的某个属性注册
Vetoable Change Listener,你需要在一个方法中监听所有的vetoable changes。

 

未完待续...