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); } } ......... ......... } ==============================================================================