next up previous contents
Next: EventSetDescriptor Up: BeanInfo Previous: 様々のDescriptor

PropertyDescriptor

PropertyDescriptor クラスのソースを見れば、このクラスがかなり複雑な構成を していることが分かります。PropertyDescriptor クラスは、 FeatureDescriptor クラスを継承しており、あるプロパティが「名前」や「値」を 持つという基本的な性質は、このFeatureDescriptor クラスによって担われている ことが分かります。

public class PropertyDescriptor extends FeatureDescriptor {
    ........
    private Class propertyType;         // Propertyの属するクラス
    private Method readMethod;          // Propertyを読み出すメソッド
    private Method writeMethod;         // Propertyを書き出すメソッド
    private boolean bound;              // Bound Propertyか?
    private boolean constrained;        // Constrained Propertyか?
    private Class propertyEditorClass;  // Propertyを編集するエディタのクラス
}

public class FeatureDescriptor {
    ........
    private boolean expert;             // Featureは "expert" か?
    private boolean hidden;             // Featureは "hidden" か?
    private String shortDescription;    // Featureの簡単な説明
    private String name;                // Featureの「名前」
    private String displayName;         // Featureのローカルな表示名
    private java.util.Hashtable table;  // Featureの「値」の格納場所
}

PropertyDescriptorクラスで拡張されたフィールドを見れば、BeansのPropertyは、 「名前」と「値」を持つだけでなく、どのようなクラスの値を持つのか、また、どの ようなメソッドによって読み書きされるのか、どのような種類(Bound、Constrained) のPropertyなのか、そして、それを編集するエディタのクラスの情報までも含んだ ものであることが分かります。

PropertyDescriptorとIntrospection

PropertyDescriptorのコンストラクタの型を見てみましょう。 いずれのコンストラクタも IntrospectionExceptionをthrowする可能性を持っている ことが分かります。もう一つ大事なことは、先にも触れましたが、Beansでは、 setter/getterと呼ばれる Propertyの値を読み書きするメソッドが、Propertyそのもの の一部を構成しているということです。

public PropertyDescriptor(String propertyName, Class beanClass)
                throws IntrospectionException;
public PropertyDescriptor(String propertyName, Class beanClass,
                String getterName, String setterName)
                throws IntrospectionException ; 
public PropertyDescriptor(String propertyName, Method getter, Method setter)
                throws IntrospectionException ;

次のリストは、PropertyDescriptorの第一のコンストラクタのソースです。 このコンストラクタは、Propertyの名前とbeanクラスを与えると、そのクラスの PropertyDescriptorを生成します。この時、次のようなNaming Ruleが使われているの が分かります。今、fooというbeanクラスのbarという名前のPropertyの PropertyDescriptorを作るものとします。コンストラクタ new PropertyDescriptor("bar", foo); は、Introspectionを用いて、まず、クラス fooの中に、"setBar"という名前のメソッドがないかを調べ、あれば、それをsetter メソッドとします。setterの引数が boolean型だったら、今度は、"isBar"という名前の getterメソッドを探します。そうでなければ、"getBar"という名前のgetterを探します。いずれの検索でも、求めるメソッドが見つからなかったら、IntrospectionExceptionが 返されます。このリストで、"isBar"へのintrospectionは、exceptionがキャッチされて いるのは何故か考えて見て下さい。

    public PropertyDescriptor(String propertyName, Class beanClass)
                throws IntrospectionException {
        setName(propertyName);
        String base = capitalize(propertyName);
        writeMethod = Introspector.findMethod(beanClass, "set" + base, 1);
        // If it's a boolean property check for an "isFoo" first.
        if (writeMethod.getParameterTypes()[0] == Boolean.TYPE) {
            try {
                readMethod = Introspector.findMethod(banClass, "is" + base, 0);
            } catch (Exception ex) {
            }
        }
        if (readMethod == null) {
            readMethod = Introspector.findMethod(beanClass, "get" + base, 0);
        }
        findPropertyType();
    }

Propertyを定義するには?

PropertyDescriptorがどのように生成されるかという考察は、「Beansで Propertyを 定義するというのはどういうことなのか」という問いに、はっきりとした回答を与え ます。少し意外なことに、あるbeanクラスがPropertyの名前とPropertyTypeが等しい フィールドを持つことは、beanのPropertyにとって必要なことではありません。 肝心なことは、ある特定の型と名前をもつメソッドが存在することです。 bean クラス A で、プロパティ xyz を定義するということは、クラスAの定義の中に、 setXyzという名前のメソッド、あるいは、getXyz(または isXyz)という名前 のメソッドを定義しておくことなのです。 この点での詳しいアルゴリズムは、java.beans.Introspectorクラスの、 getTargetPropertyInfo()メソッドのソースをよく読んでみてください。



maruyama@wakhok.ac.jp