Writing Advanced Beans |
The following documentation will help you learn about theBeanInfo
class:
- BeanInfo interface
- SimpleBeanInfo class
- Introspector class
- FeatureDescriptor class
- BeanDescriptor class
- EventSetDescriptor class
- PropertyDescriptor class
- IndexedPropertyDescriptor class
- MethodDescriptor class
- ParameterDescriptor class
- Java Core Reflection API
- JavaBeans API Specification section 8.6
A Bean can implicitly expose its properties, events, and methods by conforming to design patterns which are recognized by low-level reflection. Alternatively, a Bean can explicitly expose features in a separate, associated class that implements the
BeanInfo
interface. You can use theBeanInfo
interface (or its convenience classSimpleBeanInfo
) to explicitly expose design time information for JavaBeans-enabled builder tools.By using an associated
BeanInfo
class you can
- Expose only those features you want to expose.
- Rely on
BeanInfo
to expose some Bean features while relying on low-level reflection to expose others.- Associate an icon with the target Bean.
- Specify a customizer class.
- Segregate features into normal and expert categories.
- Provide a more descriptive display name, or additional information about a Bean feature.
BeanInfo
defines methods that return descriptors for each property, method, or event that is to be exposed in a builder tool. Here's the prototypes for these methods:PropertyDescriptor[] getPropertyDescriptors(); MethodDescriptor[] getMethodDescriptors(); EventSetDescriptor[] getEventSetDescriptors();Each of these methods returns an array of descriptors for each item that is to be exposed in a builder tool.Creating a
BeanInfo
ClassWe'll use the
ExplicitButtonBeanInfo
to illustrateBeanInfo
class creation. Here are the general steps to make aBeanInfo
class:
- Name your
BeanInfo
class. You must append the string "BeanInfo" to the target class name. If the target class name isExplicitButton
, then its associated Bean information class must be namedExplicitButtonBeanInfo
- Subclass the
SimpleBeanInfo
class. This is a convenience class the implementsBeanInfo
methods to return null, or an equivalent noop value.public class ExplicitButtonBeanInfo extends SimpleBeanInfo {Using this class saves you from implementing all theBeanInfo
methods; you only have to override those methods you need.- Override the methods you need to specify and return the properties, methods, or events that you want.
ExplicitButtonBeanInfo
overrides thegetPropertyDescriptors()
method to return four properties:public PropertyDescriptor[] getPropertyDescriptors() { try { PropertyDescriptor background = new PropertyDescriptor("background", beanClass); PropertyDescriptor foreground = new PropertyDescriptor("foreground", beanClass); PropertyDescriptor font = new PropertyDescriptor("font", beanClass); PropertyDescriptor label = new PropertyDescriptor("label", beanClass); background.setBound(true); foreground.setBound(true); font.setBound(true); label.setBound(true); PropertyDescriptor rv[] = {background, foreground, font, label}; return rv; } catch (IntrospectionException e) { throw new Error(e.toString()); } }There are two important things to note here:
- If you leave a descriptor out, that property, event or method not described will not be exposed. In other words, you can selectively expose properties, events, or methods by leaving out those you don't want exposed.
- If a feature's getter method returns null, low-level reflection is used for that feature. So you can explicitly specify properties, for example, and let low-level reflection discover the methods. If you don't override the
SimpleBeanInfo
default method, which returns null, low-level reflection will be used for that feature.- Optionally associate an icon with the target Bean.
public java.awt.Image getIcon(int iconKind) { if (iconKind == BeanInfo.ICON_MONO_16x16 || iconKind == BeanInfo.ICON_COLOR_16x16 ) { java.awt.Image img = loadImage("ExplicitButtonIcon16.gif"); return img; } if (iconKind == BeanInfo.ICON_MONO_32x32 || iconKind == BeanInfo.ICON_COLOR_32x32 ) { java.awt.Image img = loadImage("ExplicitButtonIcon32.gif"); return img; } return null; }The BeanBox displays this icon next to the Bean name in the ToolBox. You can expect builder tools to do similar.- Specify the target Bean
class
, and, if the Bean has a customizer, specify it:public BeanDescriptor getBeanDescriptor() { return new BeanDescriptor(beanClass, customizerClass); } ... private final static Class beanClass = ExplicitButton.class; private final static Class customizerClass = OurButtonCustomizer.class;Keep the
BeanInfo
class in the same directory as it's target class. The BeanBox first searches for a target Bean'sBeanInfo
class in the target Bean's package path. If noBeanInfo
is found, then the Bean information package search path (maintained by theIntrospector
) is searched. The default Bean information search path issun.beans.infos
. If noBeanInfo
class is found, then low-level reflection is used to discover a Bean's features.Using
BeanInfo
to Control What Features are ExposedIf you rely on low-level reflection to discover your Bean's features, all those properties, methods, and events that conform to the appropriate design patterns will be exposed in a builder tool. This includes any features in all base classes. If the BeanBox finds an associated
BeanInfo
class, then that information is used instead, and no more base classes are examined using reflection. In other words,BeanInfo
information overrides low-level reflection information, and prevents base class examination.By using a
BeanInfo
class, you can expose subsets of a particular Bean feature. For example, by not returning a method descriptor for a particular method, that method will not be exposed in a builder tool.When you use a
BeanInfo
class
- Base class features will not be exposed. You can retrieve base class features by using the
BeanInfo.getAdditionalBeanInfo()
method.- Properties, events, or methods that have no descriptor will not be exposed. (Omitting a property, event, or method from the list returned by the equivalent
BeanInfo
getter method eliminates it from exposure) For a particular feature, only those items returned in the descriptor array will be exposed. For example, if you return descriptors for all your Bean methods exceptfoo()
, thenfoo()
will not be exposed.- Low-level reflection will be used for features with getter methods returning null. (Omitting a particular feature, by returning null with its getter method, causes low-level reflection to be used to discover elements of that feature in the current class and all base classes.) If you return null for a particular feature's getter method, low-level reflection will be used to discover that particular feature of the target Bean.
Feature Descriptors
BeanInfo
classes contain descriptors that precisely describe the target Bean's features. The BDK implements the following descriptor classes:
FeatureDescriptor
is the base class for the other descriptor classes. It declares the aspects common to all descriptor types.BeanDescriptor
describes the target Bean's class type and name, and describes the target Bean's customizer class if it exists.PropertyDescriptor
describe the target Bean's properties.IndexedPropertyDescriptor
is a subclass ofPropertyDescriptor
, and describes the target Bean's indexed properties.EventSetDescriptor
describes the events the target Bean fires.MethodDescriptor
describes the target Bean's methods.ParameterDescriptor
describes method parameters.The
BeanInfo
interface declares methods that return arrays of the above descriptors.
Writing Advanced Beans |