BeanInfoからイベント、プロパティ、メソッドについての情報を獲得する には、どうすればいいのでしょうか? リスト5は、BeanInfoから、プロパティと メソッドのDescriptorの配列を獲得し、さらにそれらから、一つ一つのプロパティと メソッドについての情報を獲得しようというプログラムのサンプルです。 いろいろな新しいメソッドが使われていますが、名前を見れば大体の働きは想像 できると思います。
---< リスト 5 >---------------------------------------------------------------- BeanInfo bi = Introspector.getBeanInfo(Class.forName("Rectangle")); PropertyDescriptor props[] = bi.getPropertyDescriptors(); for (int i = 0; i < props.length; i++) { PropertyDescriptor pd = props[i]; System.out.println( pd.getName()+" "+pd.getPropertyType()+" "+ pd.getReadMethod()+"/"+pd.getWriteMethod() ); } System.out.println("------------"); MethodDescriptor methods[] = bi.getMethodDescriptors(); for (int i = 0; i < methods.length; i++) { MethodDescriptor md = methods[i]; System.out.println(md.getMethod().toString()); } -------------------------------------------------------------------------------
リスト5の最初の行のように、Rectangleのような普通のJavaのクラスであっても、 そこからIntrospectorが、BeanInfoを引き出してくることに注目してください。 それは、IntrospectorのgetBeanInfoメソッドが、その内部で、 プロパティやメソッドの名前についてのある想定に基づいて、reflectionを使って、 Beanの情報を集めているからです。リスト4に登場する、getTargetEventInfo(), getTargetPropertyInfo(), getTargetMethodInfo()といったメソッドのソースを、 読んでみれば、どのようなNaming Rule(Design Patternとも呼ばれます)が想定されて いるかが分かります。 RectangleクラスのFiledやMethodの名前はこのルールにあうようにつけられています。 Rectangleに対するIntrospectionは、「このBeanは、heightとwidthという プロパティを持つ。」という結果を返すことになります。
クラスRectangleでは、なんのイベント処理も行われてありませんので、リスト5では 省略しましたが、EventSetDescriptorの処理も、ほぼ同じです。 ここでも、Naming Ruleに基づいたreflectionが大事な役割を果たします。Beansの Introspectionで採用されているイベント関係のNaming Rule = Design Pattern とは、 JDK1.1で新しく導入されたイベント・モデルの Naming Ruleに他なりません。こうした命名規則に準拠してさえいれば、簡単な awtパッケージを使ったクラスを、Introspectionは、Beanと して認識します。
そうした意味では、一般のJavaのクラスと、Beansとの区別は、相対的なものでしか ありません。全てのBeansがJavaのクラスであることは自明のことですが、 どんなJavaのクラスも、言葉づかいと行儀の悪いBeansと見ることが 出来るのです。
これまで、あるクラスが与えられると、BeansのNaming Rulesに基づいて、そのクラスの reflectionが行われる過程として、BeanInfoを説明してきました。しかし、これは 単純化した説明で、正確なものではありません。実際には、クラスのreflectionに入る 前に、次のような二つの段階があり、まずそこで、BeanInfoを獲得しようとします。
第一。 Introspectionの対象となるクラスの、絶対的なクラス名のうしろに、BeanInfo をくっつけたクラスが存在すれば、そのクラスのBeanInfoを返します。例えば、今まで 見てきた Rectangleクラスの絶対名が、mylib.samples.reflect.Rectangleだとします。 この時、Introspector.getBeanInfo()は、mylib.samples.reflect.RectangleBeanInfo という名前のクラスを探して、もしそれが存在すれば、そこからBeanInfoを獲得します。
第二。 先の検索に失敗すると、getBeanInfoは、システムに定義されたシステム・ サーチ・パスを使って、RectangleBeanInfoクラスを探そうとします。現在では、この パスは、"sun.beans.infos"と定義されています。ですから、Rectangleクラスと同じ ディレクトリにRectangleBeanInfoクラスが存在しないならば、getBeanInfoは、 sun.beans.infos.RectangleBeanInfosunというクラスを探して、そこからBeanInfoを 獲得しようとします。
上記、いずれの検索にも失敗した場合、クラスに対するreflectionが BeanInfoを形成 するというわけです。他にも、いろいろ細かいことがあるのですが、大筋の理解と しては、これで十分です。