EventSetDescriptorは、新しいイベント・モデルに対応して、リスナーの型、 リスナー上のメソッド、add/removeのメソッドの情報を持ちますので、 次のようなフィールドを持ちます。リスナー上のメソッドは、一般には、 複数個存在しえますので、配列になっていることに注意してください。
public class EventSetDescriptor extends FeatureDescriptor {
private Class listenerType;
private Method[] listenerMethods;
private MethodDescriptor[] listenerMethodDescriptors;
private Method addMethod;
private Method removeMethod;
private boolean unicast;
private boolean inDefaultEventSet = true;
}
次に、このクラスのコンストラクタのsignatureを見てみたいと思います。
==============================================================================
public EventSetDescriptor(Class sourceClass, String eventSetName,
Class listenerType, String listenerMethodName)
throws IntrospectionException ...
public EventSetDescriptor(Class sourceClass,
String eventSetName,
Class listenerType,
String listenerMethodNames[],
String addListenerMethodName,
String removeListenerMethodName)
throws IntrospectionException ...
public EventSetDescriptor(String eventSetName,
Class listenerType,
Method listenerMethods[],
Method addListenerMethod,
Method removeListenerMethod)
throws IntrospectionException ...
public EventSetDescriptor(String eventSetName,
Class listenerType,
MethodDescriptor listenerMethodDescriptors[],
Method addListenerMethod,
Method removeListenerMethod)
throws IntrospectionException ...
==============================================================================
実際には、これらのコンストラクタを使わなくても、Introspectorの getTargetEventInfoメソッドの中で、メソッドのreflectionを通じて、 3番目のコンストラクタが呼び出されるのが分かります。 この部分は、reflectionのいい練習ですので、是非、解読に挑戦して下さい。 リスナー・メソッドがどのように決められているのかを考えてください。
==============================================================================
private EventSetDescriptor[] getTargetEventInfo() throws IntrospectionException {
.........
.........
if (explicit != null) {
// Add the explicit informant data to our results.
for (int i = 0 ; i < explicit.length; i++) {
addEvent(explicit[i]);
}
} else {
Method methodList[] = getDeclaredMethods(beanClass);
java.util.Hashtable adds = new java.util.Hashtable();
java.util.Hashtable removes = new java.util.Hashtable();
for (int i = 0; i < methodList.length; i++) {
Method method = methodList[i];
int mods = method.getModifiers();
if (Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {
continue;
}
String name = method.getName();
Class argTypes[] = method.getParameterTypes();
Class resultType = method.getReturnType();
if (name.startsWith("add") && argTypes.length == 1 &&
resultType == Void.TYPE) {
String compound = name.substring(3) + ":" + argTypes[0];
adds.put(compound, method);
} else if (name.startsWith("remove") && argTypes.length == 1 &&
resultType == Void.TYPE) {
String compound = name.substring(6) + ":" + argTypes[0];
removes.put(compound, method);
}
}
java.util.Enumeration keys = adds.keys();
String beanClassName = beanClass.getName();
while (keys.hasMoreElements()) {
String compound = (String) keys.nextElement();
// Skip any "add" which doesn't have a matching "remove".
if (removes.get(compound) == null) {
continue;
}
// Method name has to end in "Listener"
if (compound.indexOf("Listener:") <= 0) {
continue;
}
String listenerName = compound.substring(0, compound.indexOf(':'));
String eventName = decapitalize(listenerName.substring(0, listenerName.length()-8));
Method addMethod = (Method)adds.get(compound);
Method removeMethod = (Method)removes.get(compound);
Class argType = addMethod.getParameterTypes()[0];
// Check if the argument type is a subtype of EventListener
if (!Introspector.isSubclass(argType, eventListenerType)) {
continue;
}
// generate a list of Method objects for each of the target methods:
Method allMethods[] = argType.getMethods();
int count = 0;
for (int i = 0; i < allMethods.length; i++) {
if (isEventHandler(allMethods[i])) {
count++;
} else {
allMethods[i] = null;
}
}
Method methods[] = new Method[count];
int j = 0;
for (int i = 0; i < allMethods.length; i++) {
if (allMethods[i] != null) {
methods[j++] = allMethods[i];
}
}
EventSetDescriptor esd =
new EventSetDescriptor(eventName, argType,
methods, addMethod, removeMethod);
if (throwsException(addMethod,
java.util.TooManyListenersException.class)) {
esd.setUnicast(true);
}
addEvent(esd);
}
}
.........
.........
}
==============================================================================