Attributes of JavaBeans
The attributes of JavaBeans and the attributes referred to in general Java programs, or the attributes of objects in all object-oriented programming languages are a concept. The specific embodiment of the attributes in the program is the variables in the class. In the JavaBeans design, attributes are subdivided into four categories based on different functions: Simple, Index, Bound, and Constrained attributes.
1. Simple attributes
A simple attribute represents a variable that is accompanied by a pair of get/set methods (c-language processes or functions are called "methods" in Java programs. The property name corresponds to the get/set method name related to the property. For example, if there are setX and getX methods, it indicates that there is an attribute named "X. If there is a method named isX, it usually implies that "X" is a Boolean attribute (that is, the value of X is true or false ). For example, in the following program:
Public class alden1 extends Canvas {
String ourString = "Hello"; // The property name is ourString and the type is string.
Public alden1 () {// alden1 () is the constructor of alden1,
It has the same meaning as the constructor in C ++.
SetBackground (Color. red );
SetForeground (Color. blue );
}
/* "Set" attribute */
Public void setString (String newString ){
OurString = newString;
}
/* "Get" attribute */
Public String getString (){
Return ourString;
}
}
2. Indexed attributes
An Indexed attribute represents an array value. Use the set/get method corresponding to this attribute to obtain the values in the array. This attribute can also be set at a time or get the value of the entire array. Example:
Public class alden2 extends Canvas {
Int [] dataSet = {1, 2, 3, 4, 5, 6}; // dataSet is an indexed attribute.
Public alden2 (){
SetBackground (Color. red );
SetForeground (Color. blue );
}
/* Set the entire array */
Public void setDataSet (int [] x ){
DataSet = x;
}
/* Set a single element value in the array */
Public void setDataSet (int index, int x ){
DataSet [index] = x;
}
/* Obtain the entire array value */
Public int [] getDataSet (){
Return dataSet;
}
/* Obtain the specified Element value in the array */
Public int getDataSet (int x ){
Return dataSet [x];
}
}
3. Bound attributes
A Bound attribute notifies other objects when the value of this attribute changes. Each time the attribute value changes, this property ignishes A PropertyChange event (in a Java program, the event is also an object ). The event encapsulates the attribute name, the original value of the attribute, and the new value after the attribute changes. This type of event is transmitted to other Beans. The Beans that receive the event should be defined by themselves. When PushButton's background attribute and Dialog's background attribute bind, if PushButton's background attribute changes, the Dialog's background attribute also changes. Example:
Public class alden3 extends Canvas {
String ourString = "Hello ";
// OurString is a bound attribute
Private PropertyChangeSupport changes = new PropertyChangeSupport (this );
/** Note: Java is an object-oriented language,
If you want to use a method, you must specify the method of the object to be used,
In the following procedure, the ignition event is performed,
The method used for this operation is in the PropertyChangeSupport class.
Therefore, a changes object is declared and instantiated above,
The firePropertyChange method of changes will be used to ignify the property change event of ourString. */
Public void setString (string newString ){
String oldString = ourString;
OurString = newString;
/* The property value of ourString has changed, so the Ignition Property Change event */
Changes. firePropertyChange ("ourString", oldString, newString );
}
Public String getString (){
Return ourString;
}
/** The following code is used by the development tool.
We cannot predict which other Beans alden3 will combine into an application,
It is unpredictable which other components are related to the change if the ourString attribute of alden3 changes,
Therefore, the Beans alden3 need to reserve some interfaces for development tools,
Development tools use these interfaces,
Connect other JavaBeans objects to alden3. */
Public void addPropertyChangeListener (PropertyChangeLisener l ){
Changes. addPropertyChangeListener (l );
}
Public void removePropertyChangeListener (PropertyChangeListener l ){
Changes. removePropertyChangeListener (l );
}
Through the above Code, the development tool calls the addPropertyChangeListener method of changes and registers other javans into the listener queue l of the ourString attribute. l is a Vector Array that can store any Java objects.
The development tool can also use the removePropertyChangeListener method of changes to deregister the specified object from l, so that changes to the ourString attribute of alden3 are no longer related to this object.
Of course, when programmers write code by hand, they can also directly call these two methods to hook other Java objects with alden3.
4. Constrained attributes
The constrained attribute of a JavaBeans means that when the value of this attribute changes, other Java objects that have established a connection with this attribute can reject the change of the attribute value. The listener of the constrained attribute throws PropertyVetoException to prevent the change of the attribute value. For example, the constrained attribute in the following program is PriceInCents.
Public class JellyBeans extends Canvas {
Private PropertyChangeSupport changes = new PropertyChangeSupport (this );
Private VetoableChangeSupport Vetos = new VetoableChangeSupport (this );
/* Same as the aforementioned changes,
You can use the Vetos method in the Vetos instance of the VetoableChangeSupport object,
Disable the PriceInCents value change under specific conditions. */
......
Public void setPriceInCents (int newPriceInCents) throws PropertyVetoException {
/* In the method name, throws PropertyVetoException is used when
When other Java objects reject changes to PriceInCents,
To throw an exception. */
/* First save the original property value */
Int oldPriceInCents = ourPriceInCents;
/** Rejection event of ignition attribute change */
Vetos. fireVetoableChange ("priceInCents", new Integer (OldPriceInCents), new Integer (newPriceInCents ));
/** If other objects reject changes in priceInCents,
The program throws an exception and no longer executes the following two statements,
Method. If no other object rejects the change of priceInCents,
In the following code, we will assign ourPriceIncents a new value,
And ignition attribute change event */
OurPriceInCents = newPriceInCents;
Changes. firePropertyChange ("priceInCents", new Integer (oldPriceInCents), new Integer (newPriceInCents ));
}
/** Same as the aforementioned changes,
You also need to reserve interfaces for the PriceInCents attribute,
So that other objects can be registered into the PriceInCents rejection to change the listener queue,
Or deregister the object from it.
Public void addVetoableChangeListener (VetoableChangeListener l)
{
Vetos. addVetoableChangeListener (l );
}
Public void removeVetoableChangeListener (VetoableChangeListener l ){
Vetos. removeVetoableChangeListener (l );
}
......
}
As shown in the preceding example, a constrained attribute has two types of listeners: Property Change listener and rejection listener. The listener who rejects attribute changes has corresponding control statements in its own object code. When the monitored constrained attribute changes, the listener determines whether to reject the change of this attribute value in the control statement.
In short, whether the constrained attribute value of a certain Beans can be changed depends on whether other Beans or Java objects allow this change. The allowed or not conditions are defined by other Beans or Java objects in their own classes.
Events of JavaBeans
Event processing is the core of the JavaBeans architecture. Through the event processing mechanism, some components can be used as the event source to issue events that can be received by the descriptive environment or other components. In this way, different components can be combined in the constructor, and components communicate with each other through event transmission to form an application. In terms of concept, an event is a transmission mechanism in which a certain state changes between the "source object" and "listener object. Events have many different purposes, such as mouse events, window boundary change events, and keyboard events that are often handled in Windows. Java and JavaBeans define a general and extensible event mechanism, which can:
· Provides a public framework for defining and expanding event types and transfer models, and is suitable for a wide range of applications.
· High Integration with the Java language and environment.
· Events can be captured and ignited by the descriptive environment.
· Enable other construction tools to take some technology to directly control events during design, as well as the connections between the event source and event listener.
· The event mechanism itself does not rely on complex development tools. In particular, it should also be:
· Events that can be generated by a specified object class can be found.
· Events that can be observed (monitored) by the specified object class can be found.
· Provides a regular registration mechanism that allows you to dynamically manipulate the relationship between event sources and event listeners.
· Other virtual machines and languages are not required.
· Efficient event transmission between event sources and listeners.
· Implement neutral ing between the JavaBeans event model and the relevant other component architecture event model.
The main components of the JavaBeans event model are: the transfer of events from the event source to the listener is performed by calling the Java method of the target listener object. A specific Java method is defined for the occurrence of each specific event. These methods are centrally defined in the event listener interface, which inherits java. util. EventListener. The class that implements some or all of the methods of the event listener interface is the event listener. With the occurrence of an event, the corresponding State is usually encapsulated in the event state object, which must inherit from java. util. EventObject. The event status object is passed as a single parameter to the listener method responding to the event. The identifier of the event source that generates a specific event is: follow the prescribed design format to define the registration method for the event listener and accept references to the instance of the specified event listener interface. Sometimes, when the event listener cannot directly implement the event listener interface, or there are other additional actions, it is necessary to insert an event adapter class instance between one source and one or more listeners, to establish the relationship between them.
Event State Object)
State information related to event occurrence is generally encapsulated in an event state object, which is a subclass of java. util. EventObject. According to design habits, the name of this Event state object class should end with Event. For example:
Public class MouseMovedExampleEvent extends java. util. EventObject
{
Protected int x, y;
/* Create a mouse movement event MouseMovedExampleEvent */
MouseMovedExampleEvent (java. awt. Component source, Point location ){
Super (source );
X = location. x;
Y = location. y;
}
/* Get the mouse position */
Public Point getLocation (){
Return new Point (x, y );
}
}
EventListener Interface and event listener
Because the Java event model is called based on methods, a method to define and organize event manipulation methods is required. In JavaBeans, event manipulation methods are defined in the EventListener interface inherited from the java. util. EventListener class. according to regulations, the name of the EventListener interface should end with Listener. Any class that wants to manipulate the methods defined in the EventListener interface must implement this interface. This class is the event listener. For example:
/* First defines a mouse movement event object */
Public class MouseMovedExampleEvent
Extends java. util. EventObject {
// This class contains the status information related to the mouse movement event
...
}
/* Defines the listener interface for mouse movement events */
Interface MouseMovedExampleListener
Extends java. util. EventListener {
/* This interface defines the methods supported by the mouse movement event listener */
Void mouseMoved (MouseMovedExampleEvent mme );
}
Only the method name, method parameter, and return value type are defined in the interface. For example, the implementation of the mouseMoved method in the above interface is defined in the ArbitraryObject class below.
Class ArbitraryObject implements MouseMovedExampleListener {
Public void mouseMoved (MouseMovedExampleEvent mme)
{...}
}
ArbitraryObject is the listener of the MouseMovedExampleEvent event.
Registration and cancellation of event monitors
To register an event listener to an appropriate event source and establish an event stream between the source and event listener, the event source must provide the event listener with registration and cancellation methods. This usage process has been seen in the previous bound attribute introduction. In practice, the registration and cancellation of Event Listeners should use the standard design format:
Public void add <ListenerType> (<ListenerType> listener );
Public void remove <ListenerType> (<ListenerType> listener );
For example:
First, an event listener interface is defined:
Public interface
ModelChangedListener extends java. util. EventListener {
Void modelChanged (EventObject e );
}
Then define the event source class:
Public abstract class Model {
Private Vector listeners = new Vector (); // defines an array for storing Event listeners
/* <ListenerType> in the above design format is the following ModelChangedListener */
Public synchronized void addModelChangedListener (ModelChangedListener mcl)
{Listeners. addElement (mcl);} // register the listener into the listeners array.
Public synchronized void removeModelChangedListener (ModelChangedListener mcl)
{Listeners. removeElement (mcl); // deregister the listener from listeners
}
/* The above two methods are preceded by synchronized,
It is because when running in a multi-threaded environment,
Several objects may need to be registered and logged out at the same time,
Use synchronized to ensure synchronization between them.
Development tools or programmers use these two methods to create an event stream between the source and the listener */
Protected void policymodelchanged (){
/** The event source uses this method to notify the listener of A modelChanged event */
Vector l;
EventObject e = new EventObject (this );
/* First copy the listener to the l Array,
Freeze the EventListeners status to pass events.
So as to ensure that the event is passed to all the leaders?
The corresponding method of the target listener who has received the event does not take effect for the moment. */
Synchronized (this ){
L = (Vector) listeners. clone ();
}
For (int I = 0; I <l. size (); I ++ ){
/* Notify each listener registered in the listener queue in sequence that the modelChanged event occurs,
The event status object e is passed as a parameter to each listener in the listener queue */
(ModelChangedListener) l. elementAt (I). modelChanged (e );
}
}
}
In the program, we can see that the event source Model class explicitly calls the modelChanged method in the interface. Actually, the event state Object e is used as a parameter and passed to the modelChanged method in the listener class.
Adaption class
Adaptation classes are an extremely important part of the Java event model. In some applications, events are transmitted from the source to the listener through the Adaptation class ". For example, when the event SOURCE sends an event, and several event listening objects can receive the event, but only the specified object responds to the event, you need to insert an event adapter class between the event source and the event listener to specify which listeners should respond to the event.
The adaptation class becomes the event listener. The event source actually registers the adaptation class as the listener into the listener queue, but the real event responder is not in the listener queue, the action that the event responder should do is determined by the adaptation class. Currently, most development tools use adaptive classes to process events when generating code.
JavaBeans Customization
The JavaBeans developer can describe the content of a bean by adding a Customizer, A PropertyEditor, and a BeansInfo interface to the Beans, users of Beans can customize the appearance and actions of Beans in the constructor. A bean does not have to have BeansCustomizer, PrpertyEditor, and BeansInfo. These are optional based on actual conditions. This information is required when some Beans are complex, in the form of Wizard, users of Beans can customize a Beans. If some simple Beans do not have such information, the constructor can use its own pivoting device to view the contents of Beans, the information is displayed in standard attribute tables or event tables for users to customize Beans. The attributes, methods, and event names of Beans mentioned in the previous sections must be named in a certain format, the main function is to use development tools to view Beans. Of course, it is also convenient for programmers to use Beans in their handwritten programs, so that they can view their names and opinions.
Mizer Interface)
When a bean has its own user, its own attribute table can be displayed in the constructor. You must implement the java. Beanss. mimizer interface when defining the user agent. For example, the following is a user-defined tool for "button" Beans:
Public class OurButtonCustomizer
Extends Panel implements Customizer {
......
/* When implementing a regular Attribute Table like OurButtonCustomizer,
Make sure to implement addProperChangeListener
And removePropertyChangeListener. In this way,
The constructor can use the code to add listeners to property events. */
......
Private PropertyChangeSupport changes = new PropertyChangeSupport (this );
Public void addPropertyChangeListener (PropertyChangeListener l ){
Changes. addPropertyChangeListener (l );
Public void removePropertyChangeListener (PropertyChangeListener l ){
Changes. removePropertyChangeListener (l );
}
......
PropertyEditor Interface)
A JavaBeans provides the PropertyEditor class to create an editor for a specified attribute. This class must inherit from the java. Beanss. PropertyEditorSupport class. Programmers who construct tools and hand-written code do not directly use this class, but instantiate and call this class in BeansInfo in the next section. Example:
Public class MoleculeNameEditor extends java. Beanss. PropertyEditorSupport {
Public String [] getTags (){
String resule [] = {
"HyaluronicAcid", "Benzene", "buckmisterfullerine", "cyclohexane", "ethane", "water "};
Return resule ;}
}
In the preceding example, an Attribute Editor is created for the Tags attribute. In the constructor, you can select "HyaluronicAid" or "water" as the MoleculeName attribute from the drop-down list ".
BeansInfo Interface
Each Beans class may also have a BeansInfo class related to it, which describes the appearance of the Beans in the constructor. BeansInfo can define attributes, methods, and events, display their names, and provide simple instructions. For example:
Public class MoleculeBeansInfo extends SimpleBeansInfo {
Public PropertyDescriptor [] getPropertyDescriptors (){
Try {
PropertyDescriptor pd = new PropertyDescriptor ("moleculeName", Molecule. class );
/* Use pd to reference the MoleculeNameEditor class in the previous section, and obtain and return the moleculeName attribute */
Pd. setPropertyEditorClass (MoleculeNameEditor. class );
PropertyDescriptor result [] = {pd };
Return result;
} Catch (Exception ex ){
System. err. println ("MoleculeBeansInfo: unexpected exeption:" + ex );
Return null;
}
}
}
JavaBeans persistence
When a JavaBeans is customized in the constructor and connected to other Beans, all its statuses can be saved, the next time it is loaded into the constructor or during running, it should be the last modified information. To achieve this, you need to save the information of some fields of Beans and implement the java. io. Serializable interface when defining Beans. For example:
Public class Button
Implements java. io. Serializable {}
Fields in Beans that implement the serialization interface will be automatically saved. If you do not want to save information about some fields, You Can prefix these fields with the transient or static keyword. The information about the transient and static variables cannot be saved. Generally, all the attributes exposed by a Beans are saved, and the internal status can be selectively saved. When modifying software, Beans developers can add fields, remove references to other classes, and change the private, protected, and public statuses of a field. These do not affect the storage structure of the class. However, when you delete a field from the class, change the position of a variable in the class system, change a field to transient/static, or the original field is transient/static, and change it to another feature, will cause changes to the storage relationship.
Storage Format of JavaBeans
After the JavaBeans component is designed, it is generally stored in a Zip file with the jar extension. The jar contains information related to the JavaBeans, and the MANIFEST file specifies which classes are JavaBeans. When the JavaBeans stored in jar files are transmitted over the network, the amount of data transmitted is greatly reduced, and some resources required for running the JavaBeans are bundled together, this chapter mainly discusses some internal features of JavaBeans and its conventional design methods. For more information, see the javans specification 1.0A. With more and more support from the world's major ISVs for JavaBeans, the specifications are still evolving in some details, but the basic framework will not change much.