副标题#e#
4. Constrained属性
一个JavaBeans的constrained属性,是指当这个属性的值要产生变革时,与这个属性已成立了某种毗连的其它Java工具可反对属性值的改变。constrained属性的监听者通过抛出PropertyVetoException来阻止该属性值的改变。例:下面措施中的constrained属性是PriceInCents。
public class JellyBeans extends Canvas{
private PropertyChangeSupport changes=new PropertyChangeSupport(this);
private VetoableChangeSupport Vetos=new VetoableChangeSupport(this);
/*与前述changes沟通,
可利用VetoableChangeSupport工具的实例Vetos中的要领,
在特定条件下来阻止PriceInCents值的改变。*/
……
public void setPriceInCents(int newPriceInCents) throws PropertyVetoException {
/*要领名中throws PropertyVetoException的浸染是当有
其它Java工具反对PriceInCents的改变时,
要抛出破例。*/
/* 先生存本来的属性值*/
int oldPriceInCents=ourPriceInCents;
/**焚烧属性改变反对事件*/
vetos.fireVetoableChange("priceInCents",new Integer(OldPriceInCents),
new Integer(newPriceInCents));
/**若有其它工具反对priceInCents的改变,
则措施抛出破例,不再继承执行下面的两条语句,
要领竣事。若无其它工具反对priceInCents的改变,
则在下面的代码中把ourPriceIncents赋予新值,
并焚烧属性改变事件*/
ourPriceInCents=newPriceInCents;
changes.firePropertyChange("priceInCents",
new Integer(oldPriceInCents),
new Integer(newPriceInCents));
}
/**与前述changes沟通,
也要为PriceInCents属性预留接口,
使其它工具可注册入PriceInCents反对改变监听者行列中,
或把该工具从中注销
public void addVetoableChangeListener(VetoableChangeListener l)
{ vetos.addVetoableChangeListener(l);
}
public void removeVetoableChangeListener(VetoableChangeListener l){
vetos.removeVetoableChangeListener(l);
}
......
}
从上面的例子中可看到,一个constrained属性有两种监听者:属性变革监听者和反对属性改变的监听者。反对属性改变的监听者在本身的工具代码中有相应的节制语句,在监听到有constrained属性要产生变革时,在节制语句中判定是否应反对这个属性值的改变。
总之,某个Beans的constrained属性值能否改变取决于其它的Beans可能是Java工具是否答允这种改变。答允与否的条件由其它的Beans或Java工具在本身的类中举办界说。
#p#副标题#e#
JavaBeans的事件
事件处理惩罚是JavaBeans体系布局的焦点之一。通过事件处理惩罚机制,可让一些组件作为事件源,发出可被描写情况或其它组件吸收的事件。这样,差异的组件就可在结构东西内组合在一起,组件之间通过事件的通报举办通信,组成一个应用。从观念上讲,事件是一种在"源工具"和"监听者工具"之间,某种状态产生变革的通报机制。事件有很多差异的用途,譬喻在Windows系统中常要处理惩罚的鼠标事件、窗口界线改变事件、键盘事件等。在Java和JavaBeans中则是界说了一个一般的、可扩充的事件机制,这种机制可以或许:
对事件范例和通报的模子的界说和扩充提供一个民众框架,并适合于遍及的应用。
与Java语言和情况有较高的集成度。
事件能被描写情况捕捉和焚烧。
能使其它结构东西采纳某种技能在设计时直接节制事件,以及事件源和事件监听者之间的接洽。
事件机制自己不依赖于巨大的开拓东西。出格地,还该当:
可以或许发明指定的工具类可以生成的事件。
可以或许发明指定的工具类可以调查(监听)到的事件。
提供一个通例的注册机制,答允动态哄骗事件源与事件监听者之间的干系。
不需要其它的虚拟机和语言即可实现。
事件源与监听者之间可举办高效的事件通报。
能完成JavaBeans事件模子与相关的其它组件体系布局事件模子的中立映射。
JavaBeans事件模子的主要组成有: 事件从事件源到监听者的通报是通过对方针监听者工具的Java要领挪用举办的。对每个明晰的事件的产生,都相应地界说一个明晰的Java要领。这些要领都会合界说在事件监听者(EventListener)接口中,这个接口要担任java.util.EventListener。实现了事件监听者接口中一些或全部要领的类就是事件监听者。 陪伴着事件的产生,相应的状态凡是都封装在事件状态工具中,该工具必需担任自java.util.EventObject。事件状态工具作为单参通报给应响应该事件的监听者要领中。 发出某种特定事件的事件源的标识是:遵从划定的设计名目为事件监听者界说注册要领,并接管对指定事件监听者接话柄例的引用。 有时,事件监听者不能直接实现事件监听者接口,可能尚有其它的特别行动时,就要在一个源与其它一个或多个监听者之间插入一个事件适配器类的实例,来成立它们之间的接洽。
事件状态工具(Event State Object)
#p#分页标题#e#
与事件产生有关的状态信息一般都封装在一个事件状态工具中,这种工具是java.util.EventObject的子类。按设计习惯,这种事件状态工具类的名应以Event末了。譬喻:
public class MouseMovedExampleEvent extends java.util.EventObject
{ protected int x, y;
/* 建设一个鼠标移动事件MouseMovedExampleEvent */
MouseMovedExampleEvent(java.awt.Component source, Point location) {
super(source);
x = location.x;
y = location.y;
}
/* 获取鼠标位置*/
public Point getLocation() {
return new Point(x, y);
}}
事件监听者接口(EventListener Interface)与事件监听者
由于Java事件模子是基于要领挪用,因而需要一个界说并组织事件哄骗要领的方法。JavaBeans中,事件哄骗要领都被界说在担任了java.util.EventListener类的EventListener接口中,按划定,EventListener接口的定名要以Listener末了。任何一个类假如想哄骗在EventListener接口中界说的要领都必需以实现这个接口方法举办。这个类也就是事件监听者。譬喻:
/*先界说了一个鼠标移动事件工具*/
public class MouseMovedExampleEvent
extends java.util.EventObject {
// 在此类中包括了与鼠标移动事件有关的状态信息
...
}
/*界说了鼠标移动事件的监听者接口*/
interface MouseMovedExampleListener
extends java.util.EventListener {
/*在这个接口中界说了鼠标移动事件监听者所应支持的要领*/
void mouseMoved(MouseMovedExampleEvent mme);
}
在接口中只界说要领名,
要领的参数和返回值范例。
如:上面接口中的mouseMoved要领的
详细实现是在下面的ArbitraryObject类中界说的。
class ArbitraryObject implements MouseMovedExampleListener {
public void mouseMoved(MouseMovedExampleEvent mme)
{ ... }
}
ArbitraryObject就是MouseMovedExampleEvent事件的监听者。
事件监听者的注册与注销
为了各类大概的事件监听者把本身注册入符合的事件源中,成立源与事件监听者间的事件流,事件源必需为事件监听者提供注册和注销的要领。在前面的bound属性先容中已看到了这种利用进程,在实际中,事件监听者的注册和注销要利用尺度的设计名目:
public void add< ListenerType>(< ListenerType> listener);
public void remove< ListenerType>(< ListenerType> listener);
譬喻:
首先界说了一个事件监听者接口:
public interface
ModelChangedListener extends java.util.EventListener {
void modelChanged(EventObject e);
}
接着界说事件源类:
public abstract class Model {
private Vector listeners = new Vector(); // 界说了一个储存事件监听者的数组
/*上面设计名目中的< ListenerType>在此处等于下面的ModelChangedListener*/
public synchronized void addModelChangedListener(ModelChangedListener mcl)
{ listeners.addElement(mcl); }//把监听者注册入listeners数组中
public synchronized void removeModelChangedListener(ModelChangedListener mcl)
{ listeners.removeElement(mcl); //把监听者从listeners中注销
}
/*以上两个要领的前面均冠以synchronized,
是因为运行在多线程情况时,
大概同时有几个工具同时要举办注册和注销操纵,
利用synchronized来确保它们之间的同步。
开拓东西或措施员利用这两个要领成立源与监听者之间的事件流*/
protected void notifyModelChanged() {
/**事件源利用本要领通知监听者产生了modelChanged事件*/
Vector l;
EventObject e = new EventObject(this);
/* 首先要把监听者拷贝到l数组中,
冻结EventListeners的状态以通报事件。
这样来确保在事件通报到所有监听者之前,
已吸收了事件的方针监听者的对应要领暂不生效。*/
synchronized(this) {
l = (Vector)listeners.clone();
}
for (int i = 0; i < l.size(); i++) {
/* 依次通知注册在监听者行列中的每个监听者产生了modelChanged事件,
并把事件状态工具e作为参数通报给监听者行列中的每个监听者*/
((ModelChangedListener)l.elementAt(i)).modelChanged(e);
}
}
}
在措施中可见事件源Model类显式地挪用了接口中的modelChanged要领,实际是把事件状态工具e作为参数,通报给了监听者类中的modelChanged要领。
适配类
#p#分页标题#e#
适配类是Java事件模子中极其重要的一部门。在一些应用场所,事件从源到监听者之间的通报要通过适配类来"转发"。譬喻:当事件源发出一个事件,而有几个事件监听者工具都可吸收该事件,但只有指定工具做出回响时,就要在事件源与事件监听者之间插入一个事件适配器类,由适配器类来指定事件应该是由哪些监听者来响应。
适配类成为了事件监听者,事件源实际是把适配类作为监听者注册入监听者行列中,而真正的事件响应者并未在监听者行列中,事件响应者应做的行动由适配类抉择。今朝绝大大都的开拓东西在生成代码时,事件处理惩罚都是通过适配类来举办的。