分享
 
 
 

Getting Listeners from JavaBeansTM

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Getting Listeners from JavaBeansTM

An Amendment to the JavaBeans Specification

Hans Muller and Mark Davidson

<!-- @@@ print version @@@ -->

Presently all of the state in an AWT component that can be written can also be read, e.g. there are no write-only properties in the component API. Event listeners are a notable exception. AWT event listeners are managed according to the JavaBeans conventions with a pair of methods: addFooListener() and removeFooListener() for a listener that implements the FooListener interface.

No access is provided to the listener lists themselves. The fields that contain the listener lists may be private, package private or protected and no methods are provided to return the contents of the listener lists. This has caused some problems for Swing and other AWT clients:

The Swing UI classes have to keep references to every listener they add, just to enable removing them if the UI is changed. Swing applications contain 1000's of references like this. In general, you can't clear any JavaBeans listener list unless you've kept a private copy.

Archiving systems have to resort to implementation dependent snooping to discover the contents of listener lists.

Externalization isn't an option for classes derived from Component, like the Swing components, because the listeners are inaccessible.

To mitigate the problem in Java 2 Standard Edition (J2SE) v 1.3 we added a getListeners(Class) method to Component and to the Swing classes that defined listener lists. The getListeners(Class) method uses a Class as its argument to specify a particular listener list. For example to get all of the listeners added with addFocusListener(), one would write: getListeners(FocusListener.class).

This particular approach to exposing listener lists was taken to minimize the overall change to the AWT/Swing public API. It was not indented to be a pattern for all JavaBeans and it did not handle PropertyChangeListeners - which can be added to a single property, as in addPropertyChangeListener("myProperty", myListener).

The specific implementation of this work in the AWT and Swing is covered by 4290704.

Solution

The JavaBeans Specification has been extended so that listener lists can optionally be read. Two extensions have been added:

To the add/remove pattern for listeners: add an optional get<ListenerType>s() method that returns an array of all of the listeners for a particular list.

Extend the EventSetDescriptor class to cover the new get<ListenerType>s() method. So that BeanInfos returned for classes by Introspection can recognize the new event pattern.

The rest of the document describes the changes to the JavaBeans Specification to support the new get<ListenerType>s() extension.

The additional methods and classes presented in this amendment have been implemented for Java 2 Standard Edition (J2SE) v 1.4. JavaBeans which have been written that extend Beans in the java.awt or javax.swing packages will automatically pick up the implementation of this amendment for existing listeners when J2SE 1.4 is used . If the extended Bean defines additional listeners, then the extended Bean should implement the appropriate get<ListenerType>s() methods.

Beans Specification Amendments

All additions or changes to the JavaBeans Specification are in red

6.5 Event Listener Registration...

public void add<ListenerType>(<ListenerType listener)

public void remove<ListenerType>(<ListenerType> listener)

public <ListenerType>[] get<ListenerType>s()

...

The add<ListenerType> method adds the given listener to the set of event listeners registered for events associated with the <ListenerType>. The get<ListenerType>s method returns the set of registered event listeners. Similarly, the remove<ListenerType> method removes the given listener from the set of event listeners registered for <ListenerType> events.

The get<ListenerType>s method is optional. It was added in the XX revision of this specification consequently beans defined per earlier revisions don't support it.

6.5.1 Event Registration Examplepublic abstract class Model {

...

private List listeners = new ArrayList(0);

public synchronized void ModelChangedListener[] getModelChangedListeners() {

return (ModelChangedListener[])(listeners.toArray());

}

...

}

7.4.1 Bound properties

...

The PropertyChangeListener event listener interface is used to report updates to simple bound properties. If a bean supports bound properties then it should support the set of multi-cast event listener registration methods for PropertyChangeListeners:

public void addPropertyChangeListener(PropertyChangeListener x);

public void removePropertyChangeListener(PropertyChangeListener x);

public PropertyChangeListener[] getPropertyChangeListeners();

...

The getPropertyChangeListeners method is optional. It was added in the XX revision of this specification and as a consequence beans defined per earlier revisions don't support it. Also, the getPropertyChangeListeners method may return a mixture of PropertyChangeListeners and PropertyChangeListenerProxy objects (which implement PropertyChangeListener) if the bean supports listening on named properties. See Section 7.4.5.1 (section number may change - msd) for details.

7.4.2 Constrained properties

...

... If a bean supports constrained properties then it should support a normal set of multi-cast event listener registration methods for VetoableChangeListeners:

void addVetoableChangeListener(VetoableChangeListener x);

void removeVetoableChangeListener(VetoableChangeListener x);

VetoableChangeListener[] getVetoableChangeListeners();

The getVetoableChangeListeners method is optional. It was added in the XX revision of this specification and as a consequence beans defined per earlier revisions don't support it. Also, the getVetoableChangeListeners method may return a mixture of VetoableChangeListeners and VetoableChangeListenerProxy objects (which implement VetoableChangeListener) if the bean supports listening on named properties. See Section 7.4.5.1 (section number may change - msd) for details.

7.4.5 Optional support for listening on named propertiesIn addition to supporting the standard design pattern for adding, retrieving and removing PropertyChangeListeners shown in Section 7.4.1 above, a bean that fires PropertyChangeEvents may also support an additional set methods that allow a PropertyChangeListener to be added, retrieved and removed for a named property: void addPropertyChangeListener(String propertyName,

PropertyChangeListener listener);

void removePropertyChangeListener(String propertyName,

PropertyChangeListener listener);

PropertyChangeListener[] getPropertyChangeListeners(String propertyName);

In this case, the bean should associate the given listener with the given property name, and only invoke it's propertyChange method when the given named property has been changed.

Similarly, in addition to supporting the standard additional registration methods for adding and removing VetoableChangeListeners, beans may also support addition registration methods that are tied to a specific named property:

void addVetoableChangeListener(String propertyName,

VetoableChangeListener listener);

void removeVetoableChangeListener(String propertyName,

VetoableChangeListener listener);

VetoableChangeListener[] getVetoableChangeListeners(String propertyName);

7.4.5.1 Retrieval of listeners for named properties

When listeners for named properties are added to a bean, the zero argument retrieval method getPropertyChangeListeners (or similarly, getVetoableChangeListeners) will return all the listeners added to the bean. For beans which support named properties, the definition of getListeners() has been extended to mean that it would return the real listener, or a subclass of an EventListenerProxy for listeners added with additional parameters. Subclasses of EventListenerProxys may be used to identify the listeners associated with specific named properties.

If the calling method is interested in distinguishing the listeners from the getXXXListeners() method, then it must check each element to see if its an EventListenerProxy or subclass, perform the appropriate cast and extract the additional parameters.

For example, if a PropertyChangeListener was added with a named property to a bean with the addPropertyChangeListener("propertyName", listener), then the no argument getPropertyChangeListeners() method may return a set of PropertyChangeListeners and PropertyChangeListenerProxys. If the calling method is interested in retrieving the name of the property, then it must test each element to see if its a PropertyChangeListenerProxy.

7.4.7 A bound and constrained example... We use instances of the PropertyChangeSupport and VetoableChangeSupport classes to help us keep track of the event listeners and to deliver the actual events. import java.awt.*;

import java.beans.*;

public class JellyBean {

...

public PropertyChangeListener[] getPropertyChangeListeners() {

return changes.getPropertyChangeListeners();

}

...

public VetoableChangeListener[] getVetoableChangeListeners() {

return vetos.getVetoableChangeListeners();

}

...

}

Javadoc for EventListenerProxy

package java.util;

/**

* An abstract wrapper class for an EventListener class which associates a set of

* additional parameters with the listener. Subclasses must provide the storage and

* accessor methods for the additional arguments or parameters.

*

* Subclasses of EventListenerProxy may be returned by getListeners() methods

* as a way of associating named properties with their listeners.

*

*

* @since 1.4

*/

public class EventListenerProxy implements EventListener {

private final EventListener listener;

/**

* @param listener The listener object

* @param parameters List of parameters associated with the listener.

*/

public EventListenerProxy(EventListener listener)

/**

* @return The listener associated with this proxy.

*/

public EventListener getListener()

}

/**

* A class which extends the EventListenerProxy specifically

* for adding a named PropertyChangeListener. Instances of

* this class can be added as PropertyChangeListener to

* an object.

*

* If the object has a getPropertyChangeListeners()

* method then the array returned could be a mixture of

* PropertyChangeListener and PropertyChangeListenerProxy

* objects.

*

* For example, a Bean which supports named properties would have a two argument

* method signature for adding a PropertyChangeListener for a property:

*

* public void addPropertyChangeListener(String propertyName,

* PropertyChangeListener listener);

*

* If the Bean also implemented the zero argument get listener method:

*

* public PropertyChangeListener[] getPropertyChangeListeners();

*

* then the array may contain PropertyChangeListeners which are also

* PropertyChangeListenerProxy objects.

*

* If the calling method is interested in retrieving the named property then it

* would have to test the element to see if its a proxy class.

*

* @see java.util.EventListenerProxy

* @since 1.4

*/

public class PropertyChangeListenerProxy extends EventListenerProxy

implements PropertyChangeListener {

/**

* Constructor which binds the PropertyChangeListener to a specific property.

*

* @param listener The listener object

* @param propertyName The name of the property to listen on.

// XXX - msd NOTE: I changed the order of the arguments so that it's similar to

// PropertyChangeSupport.addPropertyChangeListener(String, PropertyChangeListener)

*/

public PropertyChangeListenerProxy(String propertyName,

PropertyChangeListener listener)

/**

* @param listener The listener object

* @param parameters List of parameters associated with the listener.

*/

public PropertyChangeListenerProxy(PropertyChangeListener listener,

Object[] parameters)

/**

* Forwards the property change event to the listener delegate.

*

* @param evt the property change event

*/

public void propertyChange(PropertyChangeEvent evt)

/**

* Returns the name of the named property associated with the

* listener.

*/

public String getPropertyName()

}

/**

* A class which extends the EventListenerProxy specifically

* for adding a named VetoableChangeListener. Instances of

* this class can be added as VetoableChangeListener to

* an object.

*

* If the object has a getVetoableChangeListeners()

* method then the array returned could be a mixture of

* VetoableChangeListener and VetoableChangeListenerProxy

* objects.

*

* @see #EventListenerProxy

* @since 1.4

*/

public class VetoableChangeListenerProxy extends EventListenerProxy

implements VetoableChangeListener {

/**

* @param propertyName The name of the property to listen on.

* @param listener The listener object

// XXX - msd NOTE: I changed the order of the arguments so that it's similar to

// PropertyChangeSupport.addPropertyChangeListener(String, PropertyChangeListener)

*/

public VetoableChangeListenerProxy(String propertyName,

VetoableChangeListener listener)

/**

* @param listener The listener object

* @param parameters List of parameters associated with the listener.

*/

public VetoableChangeListenerProxy(VetoableChangeListener listener,

Object[] parameters)

/**

* Forwards the property change event to the listener delegate.

*/

public void vetoableChange(PropertyChangeEvent evt)

/**

* Returns the name of the named property associated with the

* listener.

*/

public String getPropertyName()

}

8.4 Design Patterns for Events

...

We look for a set of methods of the form:

public void add<EventListenerType>(<EventListenerType> a)

public void remove<EventListenerType>(<EventListenerType> a)

public <EventListenerType>[] get<EventListenerType>s()

where the first two methods take the same "<EventListenerType"> type argument,...., the third method returns an array of "<EventListenerType>" objects, starts with "get" and is the plural form....

...

The get<EventListenerType>s method is optional. It was added in the XX revision of this specification and as a consequence beans defined per earlier revisions don't support it. Also, the get<EventListenerType>s method may return a mixture of <EventListenerType>s and EventListenerProxy objects if the bean supports listening on named properties. See Section 7.4.5.1 (section number may change - msd) for details.

So for example:

public void addFredListener(FredListener t);

public void removeFredListener(FredListener t);

public FredListener[] getFredListeners();

Defines a multi-cast event source

8.4.1 Unicast event sources

Implement the same changes as the multi-cast example

JavaDoc for EventSetDescriptor (additional contructors and accessor method)

/**

* This constructor creates an EventSetDescriptor from scratch using

* string names.

*

* @param sourceClass The class firing the event.

* @param eventSetName The programmatic name of the event set.

*Note that this should normally start with a lower-case character.

* @param listenerType The Class of the target interface that events

*will get delivered to.

* @param listenerMethodNames The names of the methods that will get called

*when the event gets delivered to its target listener interface.

* @param addListenerMethodName The name of the method on the event source

*that can be used to register an event listener object.

* @param removeListenerMethodName The name of the method on the event source

*that can be used to de-register an event listener object.

* @param getListenerMethodName The name of the method on the event source

*that can be used to access the array of event listener objects.

* @exception IntrospectionException if an exception occurs during

* introspection.

* @since 1.4

*/

public EventSetDescriptor(Class sourceClass,

String eventSetName,

Class listenerType,

String listenerMethodNames[],

String addListenerMethodName,

String removeListenerMethodName,

String getListenerMethodName) throws IntrospectionException

/**

* This constructor creates an EventSetDescriptor from scratch using

* java.lang.reflect.Method and java.lang.Class objects.

*

* @param eventSetName The programmatic name of the event set.

* @param listenerType The Class for the listener interface.

* @param listenerMethods An array of Method objects describing each

*of the event handling methods in the target listener.

* @param addListenerMethod The method on the event source

*that can be used to register an event listener object.

* @param removeListenerMethod The method on the event source

*that can be used to de-register an event listener object.

* @param getListenerMethod The method on the event source

*that can be used to access the array of event listener object.

* @exception IntrospectionException if an exception occurs during

* introspection.

* @since 1.4

*/

public EventSetDescriptor(String eventSetName,

Class listenerType,

Method listenerMethods[],

Method addListenerMethod,

Method removeListenerMethod,

Method getListenerMethod) throws IntrospectionException

/**

* Gets the method used to access the event listeners.

*

* @return The method used to access the array of listeners at the

* event source or null if it doesn't exist

* @since 1.4

*/

public Method getGetListenerMethod()

Implementation Details

The get<ListenerType>s() methods have been added in J2SE v 1.4 for all classes in the javax.swing and java.awt packages and sub packages which implement listener registration.

Changes to java.beans.EventSetDescriptor

The EventSetDescriptor has been amended to support the get<ListenerType>s() method. This means that two new constructors and the accessor method have been added.

For backwards compatibility, the EventSetDescriptor will not fail if the getListener() methods do not exist. However, the getGetListenerMethod() will return null if that method doesn't exist.

Changes to java.beans.PropertyChangeSupport

PropertyChangeSupport has had the following methods added:

public PropertyChangeListener[] getPropertyChangeListeners();

public PropertyChangeListener[] getPropertyChangeListeners(String propertyName);

Changes to java.beans.VetoableChangeSupport

VetoableChangeSupport has had the following methods added:

public VetoableChangeListener[] getVetoableChangeListeners();

public VetoableChangeListener[] getVetoableChangeListeners(String propertyName);

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有