User Tools

Site Tools


java:javabeans

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

java:javabeans [2014/12/24 10:42] (current)
Line 1: Line 1:
 +====== Java Beans ======
 +
 +===== Introducción =====
 +
 +Los Java Beans -en castellano granos de café java- no son otra cosa que un modelo de componentes para Java. Se estandariza la forma de definir las propiedades (métodos get y set), cómo deben notificarse cambios en los estados del componente (propiedades ligadas, constraints) y cómo acceder a colecciones de elementos (propiedades índice). ​
 +
 +Estas notas están sacadas del [[http://​java.sun.com/​docs/​books/​tutorial/​javabeans/​index.html|Tutorial de Java sobre java beans]] y he extraido aquello que se refiere sólamente al código fuente, dejando de lado los aspectos de diseño y visuales. ​
 +
 +===== Propiedades sencilla ===== 
 +
 +Un java bean sencillo: ​
 +
 +<code java>
 +
 +public class MyBean {
 +    ​
 +    /** Creates a new instance of MyBean */
 +    public MyBean() {
 +    }
 +
 +    /**
 +     * Holds value of property yourName.
 +     */
 +    private String yourName;
 +
 +    /**
 +     * Getter for property yourName.
 +     * @return Value of property yourName.
 +     */
 +    public String getYourName() {
 +        return this.yourName;​
 +    }
 +
 +    /**
 +     * Setter for property yourName.
 +     * @param yourName New value of property yourName.
 +     */
 +    public void setYourName(String yourName) {
 +        this.yourName = yourName;
 +    }
 +    ​
 +}
 +
 +</​code>​
 +
 +Las propiedades exponen dos métodos públicos: getNombrePropiedad y setNombrePropiedad. El "​set"​ siempre retorna void, el get siempre retorna el tipo de la propiedad. ​
 +
 +===== Propiedades Indexadas =====
 +
 +Cuando una propiedad debe exponer una colección de elementos (el acceso a una lista de valores), los métodos a programar son cuatro: ​
 +
 +  * String getNombrePropiedad( int index ) - devolverá el elemento de la enésima posición de la lista
 +  * String[] getNombrePropiedad() - devolverá una copia de la colección completa
 +  * void setNombrePropiedad( int index, String valor ) - establece el enésimo elemento de la lista
 +  * void setNombrePropiedad( String[] valores ) - establece la colección completa
 +
 +<code java>
 +
 +    /**
 +     * Holds value of property lines.
 +     */
 +    private String[] lines;
 +
 +    /**
 +     * Indexed getter for property lines.
 +     * @param index Index of the property.
 +     * @return Value of the property at index.
 +     */
 +    public String getLines(int index) {
 +        return this.lines[index];​
 +    }
 +
 +    /**
 +     * Getter for property lines.
 +     * @return Value of property lines.
 +     */
 +    public String[] getLines() {
 +        return this.lines;
 +    }
 +
 +    /**
 +     * Indexed setter for property lines.
 +     * @param index Index of the property.
 +     * @param lines New value of the property at index.
 +     */
 +    public void setLines(int index, String lines) {
 +        this.lines[index] = lines;
 +    }
 +
 +    /**
 +     * Setter for property lines.
 +     * @param lines New value of property lines.
 +     */
 +    public void setLines(String[] lines) {
 +        this.lines = lines;
 +    }
 +
 +</​code>​
 +
 +===== Propiedades Ligadas =====
 +
 +Lo que haremos en este caso es utilizar un objeto [[http://​java.sun.com/​javase/​6/​docs/​api/​java/​beans/​PropertyChangeListener.html|PropertyChangeListener]] para que cada vez que una de las propiedades cambie, se mande un mensaje a aquellos objetos que se hayan registrado como "​listeners ((Oyentes))"​ de nuestro bean. 
 +
 +<code java>
 +
 +import java.awt.Graphics;​
 +import java.beans.PropertyChangeListener;​
 +import java.beans.PropertyChangeSupport;​
 +import java.io.Serializable;​
 +import javax.swing.JComponent;​
 +
 +/**
 + * Bean with bound properties.
 + */
 +public class MyBean
 +        extends JComponent
 +        implements Serializable
 +{
 +    private String title;
 +    private String[] lines = new String[10];
 +
 +    private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );
 +
 +    public String getTitle()
 +    {
 +        return this.title;
 +    }
 +
 +    public void setTitle( String title )
 +    {
 +        String old = this.title;
 +        this.title = title;
 +        this.pcs.firePropertyChange( "​title",​ old, title );
 +    }
 +
 +    public String[] getLines()
 +    {
 +        return this.lines.clone();​
 +    }
 +
 +    public String getLines( int index )
 +    {
 +        return this.lines[index];​
 +    }
 +
 +    public void setLines( String[] lines )
 +    {
 +        String[] old = this.lines;
 +        this.lines = lines;
 +        this.pcs.firePropertyChange( "​lines",​ old, lines );
 +    }
 +
 +    public void setLines( int index, String line )
 +    {
 +        String old = this.lines[index];​
 +        this.lines[index] = line;
 +        this.pcs.fireIndexedPropertyChange( "​lines",​ index, old, lines );
 +    }
 +
 +    public void addPropertyChangeListener( PropertyChangeListener listener )
 +    {
 +        this.pcs.addPropertyChangeListener( listener );
 +    }
 +
 +    public void removePropertyChangeListener( PropertyChangeListener listener )
 +    {
 +        this.pcs.removePropertyChangeListener( listener );
 +    }
 +
 +}
 +
 +</​code>​
 +
 +
 +
 +
 +===== Propiedades ligadas y limitadas =====
 +
 +Existe también la posibilidad de que los listeners puedan "​vetar"​ un cambio, que son lo que se llama "​constrained properties"​ ((propiedades limitadas)).
 +
 +<code java>
 +
 +import java.io.Serializable;​
 +import java.beans.PropertyChangeListener;​
 +import java.beans.PropertyChangeSupport;​
 +import java.beans.PropertyVetoException;​
 +import java.beans.VetoableChangeListener;​
 +import java.beans.VetoableChangeSupport;​
 +import java.awt.Graphics;​
 +import javax.swing.JComponent;​
 +
 +/**
 + * Bean with constrained properties.
 + */
 +public class MyBean
 +        extends JComponent
 +        implements Serializable
 +{
 +    private String title;
 +    private String[] lines = new String[10];
 +
 +    private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );
 +    private final VetoableChangeSupport vcs = new VetoableChangeSupport( this );
 +
 +    public String getTitle()
 +    {
 +        return this.title;
 +    }
 +/**
 + * This method was modified to throw the PropertyVetoException
 + * if some vetoable listeners reject the new title value
 + */
 +    public void setTitle( String title )
 +            throws PropertyVetoException
 +    {
 +        String old = this.title;
 +        this.vcs.fireVetoableChange( "​title",​ old, title );
 +        this.title = title;
 +        this.pcs.firePropertyChange( "​title",​ old, title );
 +    }
 +
 +    public String[] getLines()
 +    {
 +        return this.lines.clone();​
 +    }
 +
 +    public String getLines( int index )
 +    {
 +        return this.lines[index];​
 +    }
 +/**
 + * This method throws the PropertyVetoException
 + * if some vetoable listeners reject the new lines value
 + */
 +    public void setLines( String[] lines )
 +            throws PropertyVetoException
 +    {
 +        String[] old = this.lines;
 +        this.vcs.fireVetoableChange( "​lines",​ old, lines );
 +        this.lines = lines;
 +        this.pcs.firePropertyChange( "​lines",​ old, lines );
 +    }
 +
 +    public void setLines( int index, String line )
 +            throws PropertyVetoException
 +    {
 +        String old = this.lines[index];​
 +        this.vcs.fireVetoableChange( "​lines",​ old, line );
 +        this.lines[index] = line;
 +        this.pcs.fireIndexedPropertyChange( "​lines",​ index, old, line );
 +    }
 +
 +    public void addPropertyChangeListener( PropertyChangeListener listener )
 +    {
 +        this.pcs.addPropertyChangeListener( listener );
 +    }
 +
 +    public void removePropertyChangeListener( PropertyChangeListener listener )
 +    {
 +        this.pcs.removePropertyChangeListener( listener );
 +    }
 +/**
 + * Registration of the VetoableChangeListener
 + */
 +    public void addVetoableChangeListener( VetoableChangeListener listener )
 +    {
 +        this.vcs.addVetoableChangeListener( listener );
 +    }
 +
 +    public void removeVetoableChangeListener( VetoableChangeListener listener )
 +    {
 +        this.vcs.removeVetoableChangeListener( listener );
 +    }
 +
 +    protected void paintComponent( Graphics g )
 +    {
 +        g.setColor( getForeground() );
 +
 +        int height = g.getFontMetrics().getHeight();​
 +        paintString( g, this.title, height );
 +
 +        if ( this.lines != null )
 +        {
 +            int step = height;
 +            for ( String line : this.lines )
 +                paintString( g, line, height += step );
 +        }
 +    }
 +
 +    private void paintString( Graphics g, String str, int height )
 +    {
 +        if ( str != null )
 +            g.drawString( str, 0, height );
 +    }
 +}
 +
 +</​code>​
 +
 +
 +===== Persistencia:​ la vida más allá de la cpu =====
 +
 +Hay dos modos de que un java bean pueda alcanzar la persistencia:​ serialización y externalización. ​
 +
 +La **serialización** se consigue implentando el interfaz Serializable,​ que podemos entender como un mero "​marcador"​ que indica que nuestro componente es puede serializarse y por lo tanto ser almacenado en disco --o transferido por la red--. ​
 +
 +Si la clase padre ya implementa Serializable,​ entonces la nuestra es también serializable. ​
 +
 +Si queremos que una clase o método no se guarde en el proceso de serialización,​ usaremos el marcador "​transient"​. ​
 +
 +Podemos hacer que la serialización no funcione por defecto implementando estos dos métodos en nuestra clase: ​
 +
 +<code java>
 +
 +private void writeObject( java.io.ObjectOutputStream out) throws IOException; ​
 +
 +private void readObject( java.io.ObjectInputStream out) throws IOException,​ ClassNotFoundException; ​
 +
 +</​code>​
 +
 +La **externalización** exige de un mayor trabajo por nuestra parte, y está pensada para que el contenido del java bean se escriba en disco. ​
 +
 +Se hace básicamente heredando el interfaz Externalizable e implementando a continuación los métodos readExternal y writeExternal. ​
 +
 +La clase que implemente Externalizable tiene que tener un constructor sin argumentos. ​
 +
 +===== Codificando y descodificando un objeto en XML =====
 +
 +La clase [[http://​java.sun.com/​j2se/​1.4.2/​docs/​api/​java/​beans/​XMLEncoder.html|XMLEncoder]] permite hacer esto. Ahí van dos ejemplos: ​
 +
 +<code java>
 +XMLEncoder e = new XMLEncoder(
 +    new BufferedOutputStream(
 +        new FileOutputStream("​Test.xml"​)));​
 +e.writeObject(object);​
 +e.close()
 +</​code>​
 +
 +<code java>
 +XMLDecoder decoder = new XMLDecoder( ​
 +              new BufferedInputStream( ​
 +              new FileInputStream( "​Test.xml"​ ) ) ); 
 +Object object = decoder.readObject(); ​
 +decoder.close();​
 +</​code>​
 +
  
java/javabeans.txt · Last modified: 2014/12/24 10:42 (external edit)