What exactly is or are JavaBeans? JavaBeans (the architecture) defines a set of rules; Java beans are ordinary Java objects that play by these rules. That is, Java beans are Java objects that conform to the JavaBeans API and design patterns. By doing so, they can be recognized and manipulated by tools (especially visual application builder environments) as well as by hand coding. Beans live and work in the Java runtime system, as do all Java objects. They communicate with their neighbors using events and other normal method invocations.
For examples of Java beans, we need look no further than the
javax.swing packages. All the familiar
components, such as
JScrollpane, follow the JavaBeans design
patterns and are beans. Much of what you learned in Chapter 16 about Swing components prepared you for
understanding beans. Although most of the Swing components aren’t very
useful in isolation, in general, beans can also be large and complex
application components, such as spreadsheets or document editors. We’ll
talk more about exactly what makes a bean a bean in a moment. For now, we
want to give you a better sense of how they are used.
One of the goals of JavaBeans is to allow components to be manipulated visually within a graphical application builder. Beans can be chosen from a palette of tools and manipulated graphically by an application designer. The Swing components we mentioned earlier are obvious candidates for this kind of usage. But Java beans can be not only simple UI components, such as buttons and sliders, but also more complex and abstract components. It is easy to get the impression that beans are, themselves, always graphical objects, but Java beans can implement any part of an application, including “invisible” parts that perform calculations, storage, and communications. Three characteristics of the JavaBeans architecture aim to make it possible to work with application components in this way:
The most important characteristic of a Java bean is simply a layer of standardization. Design patterns (i.e., coding conventions) let tools and humans recognize the basic features of a bean and manipulate it without knowing how it is implemented. We might say that beans are “self-documenting.” By examining a bean, we can tell what events it can fire and receive; we can also learn about its properties (the equivalent of its public variables) and methods. Beans can also provide explicit (“bean info”) information about their features tailored specifically for IDEs.
Reflection is an important feature of the Java language. (It’s discussed in Chapter 7.) Reflection makes it possible for Java code to inspect and manipulate new Java objects at runtime. In the context of JavaBeans, reflection lets a development tool analyze a bean’s capabilities, examine the values of its fields, and invoke its methods. Essentially, reflection allows Java objects that hook up at runtime to do all the things that could be done if the objects had been put together at compile time. Even if a bean doesn’t come bundled with any “built-in” documentation, we can still gather information about its capabilities and properties by directly inspecting the class using reflection.
Finally, the Java Serialization API allows us to “freeze-dry” a live application or application component and revive it later. This is an important capability that makes it possible to piece together applications without extensive code generation. Rather than customizing and compiling large amounts of Java code to build our application on startup, we can simply configure beans, tweak their appearance, and save them. Later, the beans can be restored with all their state and interconnections intact. This makes possible a fundamentally different way of thinking about the design process. It is easy to use serialized objects from handwritten Java code as well, so we can freely mix serialized beans with plain-old bean classes and other Java code. There is also a “long-term” object serialization mechanism that saves Java beans in an XML format that is very resilient to changes in classes.
The bean examples we mentioned have ranged from simple buttons to spreadsheets. Obviously, a button bean would be much less complex than a spreadsheet and would be used at a different level of the application’s design. At what level are beans intended to be used? The JavaBeans architecture is supposed to scale well from small to large; simple beans can be used to build larger beans. A small bean may consist of a single class; a large bean may have many. Beans can also work together through their container to provide services to other beans.
Simple beans are little more than ordinary Java objects. In fact, any Java class that has a default (empty) constructor could be considered a bean. A bean should also be serializable, although the JavaBeans specification doesn’t strictly require that. These two criteria ensure that we can create an instance of the bean dynamically and that we can later save the bean as part of a group or composition of beans. There are no other requirements. Beans are not required to inherit from a base bean class, and they don’t have to implement any special interface.
A useful bean should send and receive events and expose its
properties to the world. To do so, it follows the appropriate design
patterns for naming the relevant methods so that these features can be
automatically discovered. Most nontrivial beans intended for use in a
visual application builder IDE also provide information about themselves
in the form of a
BeanInfo class. A
BeanInfo class implements the
BeanInfo interface, which holds
methods that describe a bean’s features in more detail, along with extra
packaging, such as icons for display to the user. Normally, this “bean
info” is supplied by a separate class that is named for and supplied
with the bean.