Spring 3 - Parte 3: Inyección de Colecciones
En el tutorial anterior vimos cómo hacer la configuración de Spring para poder hacer el cableado o wiring de propiedades simples, ya fuera un valor constante o una referencia a un objeto.
Esto es muy útil cuando esperamos solo una referencia o un valor, ¿pero qué ocurre en el caso en el que necesitemos hacer la inyección de varios objetos? Java proporciona un conjunto de clases que nos permiten manejar conjuntos de objetos. Estas clases son conocidas como colecciones.
En este tutorial aprenderemos cómo realizar la inyección de dependencias en 3 tipos de colecciones ("List", "Set", y "Map") y, adicionalmente, aprenderemos a inyectar propiedades ("properties") y arreglos ("arrays"). Además veremos cómo insertar valores nulos en las propiedades de nuestros beans.
Spring ofrece cinco tipos de elementos para configuración de colecciones. La siguiente tabla muestra estos elementos y una descripción de dónde pueden usarse:
Para este ejemplo crearemos una clase a la que le inyectaremos varias colecciones, de los distintos tipos mencionados arriba, y que las recorrerá para poder mostrarlas en pantalla. Algunos de los elementos de las colecciones serán constantes y otros serán referencias a objetos de un tipo "Persona", que crearemos en unos momentos.
Lo primero que haremos es crear un nuevo proyecto en NetBeans. Para esto vamos al Menú "File->New Project...". En la ventana que se abre seleccionamos la categoría "Java" y en el tipo de proyecto "Java Application". Le damos una ubicación y un nombre al proyecto, en mi caso será "SpringColecciones". Nos aseguramos que las opciones "Create Main Class" y "Set as Main Project" estén habilitadas. Presionamos el botón "Finish" y veremos aparecer en el editor nuestra clase "Main".
Agregamos la biblioteca "Spring 3" que creamos en el primer tutorial de la serie. Hacemos clic derecho sobre el nodo "Libraries" del proyecto, en el menú que aparece elegimos la opción "Add Library...". En la ventana que se abre seleccionamos la biblioteca "Spring 3" y presionamos el botón "Add Library". Con esto los archivos de la biblioteca deben agregarse a nuestro proyecto.
Ahora crearemos un nuevo paquete que contendrá a nuestros beans, este paquete se llamará "beans". Hacemos clic derecho en el paquete en el que se encuentra nuestra clase "Main" (que en mi caso es "ejemplos.spring.colecciones") y en el menú que se abre seleccionamos la opción "New -> Java package..." y al nombre del paquete le agregamos "beans". Presionamos el botón "Finish" y con esto aparecerá nuestro nuevo paquete.
Hasta ahora nuestro proyecto debe verse así:
Ahora podemos crear nuestro archivo de configuración XML, "applicationContext.xml", en el paquete raíz (default package). Para esto hacemos clic derecho sobre el nodo "Source Packages" de nuestro proyecto, y en el menú contextual que se abre seleccionamos "new -> Other...". En la ventana que se abre, seleccionamos la categoría "Other" y como tipo de archivo "Spring XML Configuration File". Le damos un nombre al archivo, en mi caso será "applicationContext". Hacemos clic en el botón "Next". En la siguiente pantalla debemos seleccionar los namespaces que queremos que tenga nuestro archivo. No seleccionaremos ninguno. Presionamos el botón "Finish" y con eso aparecerá en nuestro editor el archivo "applicationContext.xml".
Ahora crearemos nuestra clase "Persona", dentro del paquete "beans", cuyas instancias serán inyectadas dentro de las colecciones que crearemos en unos momentos. "Persona" será una clase muy sencilla que solo tendrá 2 atributos: "nombre", de tipo String, y "edad", de tipo int, con sus respectivos setters y getters. Por lo que "Persona" queda de la siguiente forma:
También sobre-escribiremos el método "toString" de la clase "Persona". Esto con la finalidad de que al mostrar una de sus instancias, usando "System.out.println()", podamos ver los valores de sus atributos sin llamar a sus métodos getter de forma explícita:
La clase "Persona" queda de la siguiente forma:
Ahora crearemos una clase llamada "ManejadorColecciones", en el paquete "beans". Esta clase será a la que le inyectaremos las colecciones que declararemos en el archivo de configuración, y que se encargará de mostrar en consola los contenidos de estas colecciones. Esta clase tendrá una variable para cada uno de los tipos de colecciones que inyectaremos (list, arreglo, set, map, y properties), y como haremos inyección por setter (si no saben qué es esto, vean el segundo tutorial de la serie), tendrá un setterpara cada una de las propiedades anteriores, de esta forma:
Como podemos ver, "ManejadorColecciones" tiene una propiedad de cada uno de los tipos de colecciones. También podemos ver que en este caso no hemos usado "generics" al marcar las colecciones. Esto es porque dentro de la colección pondremos objetos de distintos tipos.
Ahora crearemos un método para mostrar el contenido de cada uno de estas colecciones. Estos métodos serán muy simples, solo las recorreremos en un ciclo for, y las mostraremos con un "System.out.println". Este es el método para mostrar la lista:
Este el método para mostrar el arreglo:
Este es el método para mostrar el Set:
Este es el método para mostrar el Map:
Y, finalmente, este es el método para mostrar el objeto "Properties":
Como podemos ver, los 5 métodos anteriores son muy sencillos, por lo que no necesitan más explicación. La clase "ManejadorColecciones" queda finalmente de la siguiente manera:
Ahora regresemos al archivo de "applicationContext.xml" para configurar la inyección de todos los objetos que se inyectarán a "ManejadorBeans". Lo primero que haremos es declarar dos objetos de tipo "Persona":
Ahora, haciendo uso de la inyección por setter, estableceremos los valores de los atributos "nombre" y "edad" de estos dos beans. Pueden colocar los valores que quieran:
Lo siguiente que debemos hacer es declarar un bean de tipo "ManejadorColecciones" que será el que usaremos en nuestro método "main", y al que le inyectaremos, en unos momentos más, las colecciones:
Comencemos con la inyección de cada una de nuestras colecciones.
En general, todas nuestras colecciones (incluyendo los arreglos) se declaran como beans internos, así que no tendrán un identificador propio. Comencemos inyectando las listas:
Cuando queremos declarar una referencia a un bean dentro de una lista, usamos el elemento "<ref>", y dentro de este usamos el atributo "bean" para indicar el identificador del bean al que queremos hacer referencia, en nuestro caso serán los beans "persona1" y "persona2":
Cuando queremos declarar algún valor primitivo, como un int o un String (ya lo sé, los String son objetos, no tipos primitivos, pero en Java los manejamos como si lo fueran u_u!), usamos el elemento "<value>". Dentro de ese elemento declaramos el valor que usaremos, de esta forma:
Si lo dejamos de la forma anterior, Spring entenderá ambos valores como si fueran Strings, sin embargo, si queremos declarar algún valor como otro tipo, como en el caso del "5" que queremos que sea un entero, usamos el atributo "type" del elemento "<value>" para indicar el tipo del valor. En este caso será de tipo "java.lang.Integer":
La declaración de nuestra lista queda de la siguiente forma:
Si recordamos, en una lista el orden en el que se encuentran los elementos dentro de la colección es importante. Cuando inyectamos una lista a un bean, los elementos de la misma serán inyectados en el orden en el que los declaramos en el archivo de configuración. Esto quiere decir que en este caso, el orden de los elementos en la lista será: "persona1", "persona2", "Cadena", "5".
Ahora veremos cómo inyectar los elementos para la siguiente "colección", los arreglos.
Al igual que con las listas, podemos declarar una referencia a un bean que se agregará a nuestro arreglo, usando el elemento "<ref>", o podemos inyectar un valor "primitivo" usando el elemento "<value>".
Como en nuestra clase "ManejadorColecciones" tenemos declarada la variable "arreglo" de tipo "Persona[]", solo podemos pasar referencias de tipo "Persona" al arreglo que inyectaremos. Para esto pasaremos las referencias a los beans "persona1" y "persona2" que ya tenemos declarados:
Agregaremos una Personas más a nuestro arreglo, pero en este caso en forma de bean interno:
Con esto ya tenemos declarado un arreglo de 3 elementos, de tipo "Persona", que serán inyectados en el momento de que nuestro bean sea creado.
La declaración del arreglo queda así:
En los arreglos, igual que en las listas, el orden en el que se encuentran los elementos dentro de la colección es importante. En este caso también, los elementos del arreglo serán inyectados en el orden en el que los declaramos en el archivo de configuración. Esto quiere decir que en este caso, el orden de los elementos en la lista será: "persona2", "persona1", "Persona Interna".
Pasemos a ver cómo inyectar el siguiente tipo de colección, los conjuntos o Sets.
Igual que en los casos anteriores, podemos pasar referencias a otros beans, usando en elemento "<ref>", o valores "primitivos", usando el elemento "<value>". Nosotros pasaremos cuatro referencias a 2 beans: 2 referencias al bean "persona1" y 2 referencias al bean "persona2", de la siguiente forma:
¿Por qué hacemos esto? Bueno, esto lo hemos hecho porque los Sets son un tipo especial de colección que NO permite tener elementos repetidos. Esto quiere decir que aunque hayamos pasado 4 referencias, como en realidad solo estamos pasando 2 objetos (y 2 repetidos) la colección al final solo tendrá 2 objetos, esto lo veremos al momento de mostrar los valores en la consola.
Al final, la declaración de nuestro conjunto queda de la siguiente forma:
Ahora veamos cómo inyectar nuestra cuarta colección, los mapas.
Recordemos que un mapa es una colección que tiene elementos de tipo llave-valor, donde tanto la llave como el valor pueden ser de cualquier tipo. Para declarar los miembros del mapa, usamos el elemento "<entry>". Dentro de este elemento podemos indicar dos tipos de llaves, una llave que es un valor, usando el atributo "key", que es tomado como String, o una llave que es una referencia a un bean, usando el atributo "key-ref". De la misma forma, podemos declarar dos tipos de valores, unos que son referencias a otros beans, usando "value-ref", y otros que son valores que son tomados como String, usando "value". La siguiente tabla da el nombre y una descripción de estos atributos:
Nosotros inyectaremos 4 entradas a nuestro mapa. Trataremos de combinar varios tipos de objetos, tanto de beans como de valores. La primer entrada tendrá como llave una cadena y como valor una referencia a uno de nuestros beans de tipo "Persona":
La siguiente entrada será al revés, la llave será una referencia a uno de los beans de tipo "Persona" y el valor será una cadena:
La tercer entrada tendrá como llave una cadena y como valor otra cadena:
La cuarta y última entrada tendrá como llave una referencia a un objeto "Persona" y como valor otra referencia a un objeto "Persona":
La declaración final de nuestro mapa queda de la siguiente forma:
Veremos cómo configurar nuestra última "colección", las propiedades.
Spring proporciona el elemento "<props>" para declarar atributos de tipo "java.util.Properties".
Para agregar cada uno de los miembros de las propiedades tenemos dos formas. La primera es usando el elemento "<prop>", en el cual indicamos la llave usando el atributo "key", y el valor lo colocamos como contenido del elemento. Por ejemplo, si quisiéramos declarar cuatro propiedades: nombre, país, sitio, y facebook, lo haríamos de la siguiente manera:
La segunda forma es aprovechando el soporte que nos proporciona Spring para manejo de propiedades usando su "PropertyEditor" integrado para escribir directamente las llaves y valores de las propiedades, como cuerpo del elemento "<value>" que colocamos directamente dentro de la propiedad (sin hacer uso del elemento "<props>"), de esta forma:
Y esto es todo, ya tenemos configuradas todas las colecciones de nuestro ejemplo. Al final el archivo de configuración, "applicationContext.xml", queda de la siguiente forma:
Lo siguiente que debemos hacer es, en nuestro método "main", crear un objeto de tipo "ApplicationContext" para poder obtener nuestros beans. Para ver más a detalle cómo hacer esto, pueden consultar el segundo tutorial de la serie, aquí lo resumiré todo diciendo que crearemos una instancia de "ClassPathXmlApplicationContext" y pasaremos como parámetro de su constructor la ubicación del archivo de configuración dentro del classpath, de la siguiente forma:
Lo siguiente que haremos es obtener una referencia al bean "manejador", declarado en el archivo de configuración, usando el método "getBean" de nuestro objeto "ApplicationContext":
Para terminar invocaremos, en el objeto "manejador", cada uno de los métodos para mostrar los valores de las colecciones, de la siguiente forma:
El método "main" queda de la siguiente forma:
Al ejecutar nuestra aplicación obtenemos la siguiente salida:
Analicemos un poco esta salida.
La primera que obtenemos es la salida de la lista. En esta, podemos comprobar que los elementos de la misma se encuentran en el mismo orden en el que los declaramos en el archivo de configuración. Primero los dos beans de tipo "Persona", después la cadena "Cadena" que declaramos como un valor, y finalmente el valor "5" que declaramos como un objeto de tipo "java.lang.Integer":
En la siguiente parte de la salida, tenemos el valor del arreglo. Aquí nuevamente, los elementos se encuentran en el mismo orden en el que los declaramos en el archivo de configuración. Tenemos primero los dos beans de tipo "Persona", y después el bean interno que declaramos, con el "nombre" de "Persona Nueva" y la "edad" de "10":
--
Posteriormente está el segmento de la salida correspondiente con el Set. Aquí vemos que aunque en el archivo de configuración declaramos 4 miembros para esta colección, al final en esta solo se insertan 2 objetos, ya que los Sets son colecciones que no permiten duplicados:
La que sigue es la salida de los elementos del mapa. Aquí podemos observar que, efectivamente, tenemos una combinación tanto de llaves como de valores de tipos "Persona" y "String", de la misma forma que en el archivo de configuración:
La última parte de la salida es la que corresponde con las propiedades. En esta, podemos ver que tanto las llaves como los valores son de tipo "String":
Como vemos, nuestras colecciones se han inyectado de forma correcta ^_^.
Tal vez algunos se hayan preguntado ¿y qué ocurre si quiero insertar una propiedad con un valor de "null", o un elemento de las colecciones como "null"? Bueno, responderemos esta pregunta en la última parte del tutorial
Aunque en Java las referencias a objetos son por default nulas, algunas veces asumir esto no es suficiente para lograr nuestros propósitos.
Para establecer una propiedad como "null" usamos el elemento... "<null />". Por ejemplo, si quisiéramos establecer la propiedad "nombre" de un bean de tipo "Persona" como "null", lo declararíamos de la siguiente forma:
Y eso es todo lo que debemos hacer ^_^.
Hemos llegado al final de este tercer tutorial sobre Spring 3, espero que les sea de utilidad. No olviden dejar sus dudas, comentarios y sugerencias.
Saludos.
Esto es muy útil cuando esperamos solo una referencia o un valor, ¿pero qué ocurre en el caso en el que necesitemos hacer la inyección de varios objetos? Java proporciona un conjunto de clases que nos permiten manejar conjuntos de objetos. Estas clases son conocidas como colecciones.
En este tutorial aprenderemos cómo realizar la inyección de dependencias en 3 tipos de colecciones ("List", "Set", y "Map") y, adicionalmente, aprenderemos a inyectar propiedades ("properties") y arreglos ("arrays"). Además veremos cómo insertar valores nulos en las propiedades de nuestros beans.
Spring ofrece cinco tipos de elementos para configuración de colecciones. La siguiente tabla muestra estos elementos y una descripción de dónde pueden usarse:
Elemento | Útil para |
---|---|
<list> | Wiring de una lista de valores, que permite duplicados y mantienen un orden. |
<array> | Wiring de un arreglo de objetos, que permite duplicados y mantienen un orden. |
<set> | Wiring de un conjunto de valores, asegurando que no hay duplicados. |
<map> | Wiring de una colección de pares nombre-valor donde el nombre y el valor pueden ser de cualquier tipo. |
<props> | Wiring de una colección de pares nombre-valor donde el nombre y el valor son de tipo String. |
Para este ejemplo crearemos una clase a la que le inyectaremos varias colecciones, de los distintos tipos mencionados arriba, y que las recorrerá para poder mostrarlas en pantalla. Algunos de los elementos de las colecciones serán constantes y otros serán referencias a objetos de un tipo "Persona", que crearemos en unos momentos.
Lo primero que haremos es crear un nuevo proyecto en NetBeans. Para esto vamos al Menú "File->New Project...". En la ventana que se abre seleccionamos la categoría "Java" y en el tipo de proyecto "Java Application". Le damos una ubicación y un nombre al proyecto, en mi caso será "SpringColecciones". Nos aseguramos que las opciones "Create Main Class" y "Set as Main Project" estén habilitadas. Presionamos el botón "Finish" y veremos aparecer en el editor nuestra clase "Main".
Agregamos la biblioteca "Spring 3" que creamos en el primer tutorial de la serie. Hacemos clic derecho sobre el nodo "Libraries" del proyecto, en el menú que aparece elegimos la opción "Add Library...". En la ventana que se abre seleccionamos la biblioteca "Spring 3" y presionamos el botón "Add Library". Con esto los archivos de la biblioteca deben agregarse a nuestro proyecto.
Ahora crearemos un nuevo paquete que contendrá a nuestros beans, este paquete se llamará "beans". Hacemos clic derecho en el paquete en el que se encuentra nuestra clase "Main" (que en mi caso es "ejemplos.spring.colecciones") y en el menú que se abre seleccionamos la opción "New -> Java package..." y al nombre del paquete le agregamos "beans". Presionamos el botón "Finish" y con esto aparecerá nuestro nuevo paquete.
Hasta ahora nuestro proyecto debe verse así:
Ahora podemos crear nuestro archivo de configuración XML, "applicationContext.xml", en el paquete raíz (default package). Para esto hacemos clic derecho sobre el nodo "Source Packages" de nuestro proyecto, y en el menú contextual que se abre seleccionamos "new -> Other...". En la ventana que se abre, seleccionamos la categoría "Other" y como tipo de archivo "Spring XML Configuration File". Le damos un nombre al archivo, en mi caso será "applicationContext". Hacemos clic en el botón "Next". En la siguiente pantalla debemos seleccionar los namespaces que queremos que tenga nuestro archivo. No seleccionaremos ninguno. Presionamos el botón "Finish" y con eso aparecerá en nuestro editor el archivo "applicationContext.xml".
Ahora crearemos nuestra clase "Persona", dentro del paquete "beans", cuyas instancias serán inyectadas dentro de las colecciones que crearemos en unos momentos. "Persona" será una clase muy sencilla que solo tendrá 2 atributos: "nombre", de tipo String, y "edad", de tipo int, con sus respectivos setters y getters. Por lo que "Persona" queda de la siguiente forma:
public class Persona
{
private String nombre;
private int edad;
public int getEdad()
{
return edad;
}
public void setEdad(int edad)
{
this.edad = edad;
}
public String getNombre()
{
return nombre;
}
public void setNombre(String nombre)
{
this.nombre = nombre;
}
}
También sobre-escribiremos el método "toString" de la clase "Persona". Esto con la finalidad de que al mostrar una de sus instancias, usando "System.out.println()", podamos ver los valores de sus atributos sin llamar a sus métodos getter de forma explícita:
@Override
public String toString()
{
return new StringBuilder("nombre: ").append(nombre).append(", edad: ").append(edad).toString();
}
La clase "Persona" queda de la siguiente forma:
public class Persona
{
private String nombre;
private int edad;
public int getEdad()
{
return edad;
}
public void setEdad(int edad)
{
this.edad = edad;
}
public String getNombre()
{
return nombre;
}
public void setNombre(String nombre)
{
this.nombre = nombre;
}
@Override
public String toString()
{
return new StringBuilder("nombre: ").append(nombre).append(", edad: ").append(edad).toString();
}
}
Ahora crearemos una clase llamada "ManejadorColecciones", en el paquete "beans". Esta clase será a la que le inyectaremos las colecciones que declararemos en el archivo de configuración, y que se encargará de mostrar en consola los contenidos de estas colecciones. Esta clase tendrá una variable para cada uno de los tipos de colecciones que inyectaremos (list, arreglo, set, map, y properties), y como haremos inyección por setter (si no saben qué es esto, vean el segundo tutorial de la serie), tendrá un setterpara cada una de las propiedades anteriores, de esta forma:
public class ManejadorColecciones
{
private List lista;
private Persona[] arreglo;
private Set conjunto;
private Map mapa;
private Properties propiedades;
public void setArreglo(Persona[] arreglo)
{
this.arreglo = arreglo;
}
public void setConjunto(Set conjunto)
{
this.conjunto = conjunto;
}
public void setLista(List lista)
{
this.lista = lista;
}
public void setMapa(Map mapa)
{
this.mapa = mapa;
}
public void setPropiedades(Properties propiedades)
{
this.propiedades = propiedades;
}
}
Como podemos ver, "ManejadorColecciones" tiene una propiedad de cada uno de los tipos de colecciones. También podemos ver que en este caso no hemos usado "generics" al marcar las colecciones. Esto es porque dentro de la colección pondremos objetos de distintos tipos.
Ahora crearemos un método para mostrar el contenido de cada uno de estas colecciones. Estos métodos serán muy simples, solo las recorreremos en un ciclo for, y las mostraremos con un "System.out.println". Este es el método para mostrar la lista:
public void muestraLista()
{
System.out.println("---Mostrando lista---");
for(Object o : lista)
{
System.out.println(o.getClass() + ": " + o);
}
}
Este el método para mostrar el arreglo:
public void muestraArreglo()
{
System.out.println("---Mostrando arreglo---");
for(Object o : arreglo)
{
System.out.println(o.getClass() + ": " + o);
}
}
Este es el método para mostrar el Set:
public void muestraConjunto()
{
System.out.println("---Mostrando conjunto---");
for (Iterator it = conjunto.iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println(o.getClass() + ": " + o);
}
}
Este es el método para mostrar el Map:
public void muestraMapa()
{
System.out.println("---Mostrando mapa---");
for (Iterator it = mapa.keySet().iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println("[llave] " + o.getClass() + ": " + o + ", [valor]" + mapa.get(o).getClass() + ": " + mapa.get(o) );
}
}
Y, finalmente, este es el método para mostrar el objeto "Properties":
public void muestraPropiedades()
{
System.out.println("\n---Mostrando propiedades---");
for (Iterator it = propiedades.keySet().iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println("[llave] " + o.getClass() + ": " + o + ", [valor]" + propiedades.get(o).getClass() + ": " + propiedades.get(o) );
}
}
Como podemos ver, los 5 métodos anteriores son muy sencillos, por lo que no necesitan más explicación. La clase "ManejadorColecciones" queda finalmente de la siguiente manera:
public class ManejadorColecciones
{
private List lista;
private Persona[] arreglo;
private Set conjunto;
private Map mapa;
private Properties propiedades;
public void muestraLista()
{
System.out.println("\n---Mostrando lista---");
for (Object o : lista)
{
System.out.println(o.getClass() + ": " + o);
}
}
public void muestraArreglo()
{
System.out.println("\n---Mostrando arreglo---");
for (Object o : arreglo)
{
System.out.println(o.getClass() + ": " + o);
}
}
public void muestraConjunto()
{
System.out.println("\n---Mostrando conjunto---");
for (Iterator it = conjunto.iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println(o.getClass() + ": " + o);
}
}
public void muestraMapa()
{
System.out.println("\n---Mostrando mapa---");
for (Iterator it = mapa.keySet().iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println("[llave] " + o.getClass() + ": " + o + ", [valor]" + mapa.get(o).getClass() + ": " + mapa.get(o) );
}
}
public void muestraPropiedades()
{
System.out.println("\n---Mostrando propiedades---");
for (Iterator it = propiedades.keySet().iterator(); it.hasNext();)
{
Object o = it.next();
System.out.println("[llave] " + o.getClass() + ": " + o + ", [valor]" + propiedades.get(o).getClass() + ": " + propiedades.get(o) );
}
}
public void setArreglo(Persona[] arreglo)
{
this.arreglo = arreglo;
}
public void setConjunto(Set conjunto)
{
this.conjunto = conjunto;
}
public void setLista(List lista)
{
this.lista = lista;
}
public void setMapa(Map mapa)
{
this.mapa = mapa;
}
public void setPropiedades(Properties propiedades)
{
this.propiedades = propiedades;
}
}
Ahora regresemos al archivo de "applicationContext.xml" para configurar la inyección de todos los objetos que se inyectarán a "ManejadorBeans". Lo primero que haremos es declarar dos objetos de tipo "Persona":
<bean id="persona1" class="ejemplos.spring.colecciones.beans.Persona">
</bean>
<bean id="persona2" class="ejemplos.spring.colecciones.beans.Persona">
</bean>
Ahora, haciendo uso de la inyección por setter, estableceremos los valores de los atributos "nombre" y "edad" de estos dos beans. Pueden colocar los valores que quieran:
<bean id="persona1" class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona1" />
<property name="edad" value="26" />
</bean>
<bean id="persona2" class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona2" />
<property name="edad" value="62" />
</bean>
Lo siguiente que debemos hacer es declarar un bean de tipo "ManejadorColecciones" que será el que usaremos en nuestro método "main", y al que le inyectaremos, en unos momentos más, las colecciones:
<bean id="manejador" class="ejemplos.spring.colecciones.beans.ManejadorColecciones">
</bean>
Comencemos con la inyección de cada una de nuestras colecciones.
En general, todas nuestras colecciones (incluyendo los arreglos) se declaran como beans internos, así que no tendrán un identificador propio. Comencemos inyectando las listas:
INYECCIÓN DE LISTAS
Para declarar una lista en el archivo de configuración usamos el elemento "<list>" en la propiedad correspondiente, que en este caso se llama "lista":
<property name="lista">
<list>
</list>
</property>
Cuando queremos declarar una referencia a un bean dentro de una lista, usamos el elemento "<ref>", y dentro de este usamos el atributo "bean" para indicar el identificador del bean al que queremos hacer referencia, en nuestro caso serán los beans "persona1" y "persona2":
<property name="lista">
<list>
<ref bean="persona1" />
<ref bean="persona2" />
</list>
</property>
Cuando queremos declarar algún valor primitivo, como un int o un String (ya lo sé, los String son objetos, no tipos primitivos, pero en Java los manejamos como si lo fueran u_u!), usamos el elemento "<value>". Dentro de ese elemento declaramos el valor que usaremos, de esta forma:
<value>Cadena</value>
<value>5</value>
Si lo dejamos de la forma anterior, Spring entenderá ambos valores como si fueran Strings, sin embargo, si queremos declarar algún valor como otro tipo, como en el caso del "5" que queremos que sea un entero, usamos el atributo "type" del elemento "<value>" para indicar el tipo del valor. En este caso será de tipo "java.lang.Integer":
<value type="java.lang.Integer">5</value>
La declaración de nuestra lista queda de la siguiente forma:
<property name="lista">
<list>
<ref bean="persona1" />
<ref bean="persona2" />
<value>Cadena</value>
<value type="java.lang.Integer">5</value>
</list>
</property>
Si recordamos, en una lista el orden en el que se encuentran los elementos dentro de la colección es importante. Cuando inyectamos una lista a un bean, los elementos de la misma serán inyectados en el orden en el que los declaramos en el archivo de configuración. Esto quiere decir que en este caso, el orden de los elementos en la lista será: "persona1", "persona2", "Cadena", "5".
Ahora veremos cómo inyectar los elementos para la siguiente "colección", los arreglos.
INYECCIÓN DE ARREGLOS
Ahora inyectaremos un arreglo a nuestro bean "ManejadorColecciones". Spring proporciona el elemento "<array>" para declarar un arreglo dentro del archivo de configuración:
<property name="arreglo">
<array>
</array>
</property>
Al igual que con las listas, podemos declarar una referencia a un bean que se agregará a nuestro arreglo, usando el elemento "<ref>", o podemos inyectar un valor "primitivo" usando el elemento "<value>".
Como en nuestra clase "ManejadorColecciones" tenemos declarada la variable "arreglo" de tipo "Persona[]", solo podemos pasar referencias de tipo "Persona" al arreglo que inyectaremos. Para esto pasaremos las referencias a los beans "persona1" y "persona2" que ya tenemos declarados:
<array>
<ref bean="persona2" />
<ref bean="persona1" />
</array>
Agregaremos una Personas más a nuestro arreglo, pero en este caso en forma de bean interno:
<array>
<ref bean="persona2" />
<ref bean="persona1" />
<bean class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona Nueva" />
<property name="edad" value="10" />
</bean>
</array>
Con esto ya tenemos declarado un arreglo de 3 elementos, de tipo "Persona", que serán inyectados en el momento de que nuestro bean sea creado.
La declaración del arreglo queda así:
<property name="arreglo">
<array>
<ref bean="persona2" />
<ref bean="persona1" />
<bean class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona Nueva" />
<property name="edad" value="10" />
</bean>
</array>
</property>
En los arreglos, igual que en las listas, el orden en el que se encuentran los elementos dentro de la colección es importante. En este caso también, los elementos del arreglo serán inyectados en el orden en el que los declaramos en el archivo de configuración. Esto quiere decir que en este caso, el orden de los elementos en la lista será: "persona2", "persona1", "Persona Interna".
Pasemos a ver cómo inyectar el siguiente tipo de colección, los conjuntos o Sets.
INYECCIÓN DE SETS
Cuando queremos inyectar un Set a un bean, usamos el elemento "<set>" del archivo de configuración:
<property name="conjunto">
<set>
</set>
</property>
Igual que en los casos anteriores, podemos pasar referencias a otros beans, usando en elemento "<ref>", o valores "primitivos", usando el elemento "<value>". Nosotros pasaremos cuatro referencias a 2 beans: 2 referencias al bean "persona1" y 2 referencias al bean "persona2", de la siguiente forma:
<set>
<ref bean="persona1" />
<ref bean="persona2" />
<ref bean="persona2" />
<ref bean="persona1" />
</set>
¿Por qué hacemos esto? Bueno, esto lo hemos hecho porque los Sets son un tipo especial de colección que NO permite tener elementos repetidos. Esto quiere decir que aunque hayamos pasado 4 referencias, como en realidad solo estamos pasando 2 objetos (y 2 repetidos) la colección al final solo tendrá 2 objetos, esto lo veremos al momento de mostrar los valores en la consola.
Al final, la declaración de nuestro conjunto queda de la siguiente forma:
<property name="conjunto">
<set>
<ref bean="persona1" />
<ref bean="persona2" />
<ref bean="persona2" />
<ref bean="persona1" />
</set>
</property>
Ahora veamos cómo inyectar nuestra cuarta colección, los mapas.
INYECCIÓN DE MAPS
Para hacer inyección de Maps, Spring proporciona el elemento… así es, adivinaron, el elemento "<map>":
<property name="mapa">
<map>
</map>
</property>
Recordemos que un mapa es una colección que tiene elementos de tipo llave-valor, donde tanto la llave como el valor pueden ser de cualquier tipo. Para declarar los miembros del mapa, usamos el elemento "<entry>". Dentro de este elemento podemos indicar dos tipos de llaves, una llave que es un valor, usando el atributo "key", que es tomado como String, o una llave que es una referencia a un bean, usando el atributo "key-ref". De la misma forma, podemos declarar dos tipos de valores, unos que son referencias a otros beans, usando "value-ref", y otros que son valores que son tomados como String, usando "value". La siguiente tabla da el nombre y una descripción de estos atributos:
Atributo | Propósito |
---|---|
key | Especifica la llave de la entrada del mapa como un String. |
key-ref | Especifica la llave de la entrada del mapa como una referencia a un bean. |
Value | Especifica el valor de la entrada del mapa como un String. |
value-ref | Especifica el valor de la entrada del mapa como una referencia a un bean. |
Nosotros inyectaremos 4 entradas a nuestro mapa. Trataremos de combinar varios tipos de objetos, tanto de beans como de valores. La primer entrada tendrá como llave una cadena y como valor una referencia a uno de nuestros beans de tipo "Persona":
<entry key="persona1" value-ref="persona1" />
La siguiente entrada será al revés, la llave será una referencia a uno de los beans de tipo "Persona" y el valor será una cadena:
<entry key-ref="persona2" value="otra persona" />
La tercer entrada tendrá como llave una cadena y como valor otra cadena:
<entry key="sin persona" value="no personas" />
La cuarta y última entrada tendrá como llave una referencia a un objeto "Persona" y como valor otra referencia a un objeto "Persona":
<entry key-ref="persona1" value-ref="persona2" />
La declaración final de nuestro mapa queda de la siguiente forma:
<property name="mapa">
<map>
<entry key="persona1" value-ref="persona1" />
<entry key-ref="persona2" value="otra persona" />
<entry key="sin persona" value="no personas" />
<entry key-ref="persona1" value-ref="persona2" />
</map>
</property>
Veremos cómo configurar nuestra última "colección", las propiedades.
INYECCIÓN DE PROPIEDADES
Las propiedades son muy similares a los mapas; son colecciones donde se tienen pares llave-valor. De hecho la clase "Properties" implementa la interface "Map". La diferencia principal es que, mientras que en los mapas la llave y el valor pueden ser de cualquier tipo, en las propiedades ambos elementos solo pueden ser de tipo String.Spring proporciona el elemento "<props>" para declarar atributos de tipo "java.util.Properties".
<property name="propiedades">
<props>
</props>
</property>
Para agregar cada uno de los miembros de las propiedades tenemos dos formas. La primera es usando el elemento "<prop>", en el cual indicamos la llave usando el atributo "key", y el valor lo colocamos como contenido del elemento. Por ejemplo, si quisiéramos declarar cuatro propiedades: nombre, país, sitio, y facebook, lo haríamos de la siguiente manera:
<prop key="nombre">Alex</prop>
<prop key="pais">Mexico</prop>
<prop key="sitio">http://javatutoriales.blogspot.com/</prop>
<prop key="facebook">http://www.facebook.com/pages/Java-Tutoriales/121935157864634</prop>
La segunda forma es aprovechando el soporte que nos proporciona Spring para manejo de propiedades usando su "PropertyEditor" integrado para escribir directamente las llaves y valores de las propiedades, como cuerpo del elemento "<value>" que colocamos directamente dentro de la propiedad (sin hacer uso del elemento "<props>"), de esta forma:
<property name="propiedades">
<value>
nombre=Alex
pais=Mexico
sitio=http://javatutoriales.blogspot.com
facebook=http://www.facebook.com/pages/Java-Tutoriales/121935157864634
</value>
</property>
Y esto es todo, ya tenemos configuradas todas las colecciones de nuestro ejemplo. Al final el archivo de configuración, "applicationContext.xml", queda de la siguiente forma:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.Springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.Springframework.org/schema/beans http://www.Springframework.org/schema/beans/Spring-beans-3.0.xsd">
<bean id="persona1" class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona1" />
<property name="edad" value="26" />
</bean>
<bean id="persona2" class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona2" />
<property name="edad" value="62" />
</bean>
<bean id="manejador" class="ejemplos.spring.colecciones.beans.ManejadorColecciones">
<property name="lista">
<list>
<ref bean="persona1" />
<ref bean="persona2" />
<value>Cadena</value>
<value type="java.lang.Integer">5</value>
</list>
</property>
<property name="arreglo">
<array>
<ref bean="persona2" />
<ref bean="persona1" />
<bean class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre" value="Persona Nueva" />
<property name="edad" value="10" />
</bean>
</array>
</property>
<property name="conjunto">
<set>
<ref bean="persona1" />
<ref bean="persona2" />
<ref bean="persona2" />
<ref bean="persona1" />
</set>
</property>
<property name="mapa">
<map>
<entry key="persona1" value-ref="persona1" />
<entry key-ref="persona2" value="otra persona" />
<entry key="sin persona" value="no personas" />
<entry key-ref="persona1" value-ref="persona2" />
</map>
</property>
<property name="propiedades">
<props>
<prop key="nombre">Alex</prop>
<prop key="pais">Mexico</prop>
<prop key="sitio">http://javatutoriales.blogspot.com/</prop>
<prop key="facebook">http://www.facebook.com/pages/Java-Tutoriales/121935157864634</prop>
</props>
</property>
</bean>
</beans>
Lo siguiente que debemos hacer es, en nuestro método "main", crear un objeto de tipo "ApplicationContext" para poder obtener nuestros beans. Para ver más a detalle cómo hacer esto, pueden consultar el segundo tutorial de la serie, aquí lo resumiré todo diciendo que crearemos una instancia de "ClassPathXmlApplicationContext" y pasaremos como parámetro de su constructor la ubicación del archivo de configuración dentro del classpath, de la siguiente forma:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Lo siguiente que haremos es obtener una referencia al bean "manejador", declarado en el archivo de configuración, usando el método "getBean" de nuestro objeto "ApplicationContext":
ManejadorColecciones manejador = applicationContext.getBean("manejador", ManejadorColecciones.class);
Para terminar invocaremos, en el objeto "manejador", cada uno de los métodos para mostrar los valores de las colecciones, de la siguiente forma:
manejador.muestraLista();
manejador.muestraArreglo();
manejador.muestraConjunto();
manejador.muestraMapa();
manejador.muestraPropiedades();
El método "main" queda de la siguiente forma:
public static void main(String[] args)
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ManejadorColecciones manejador = applicationContext.getBean("manejador", ManejadorColecciones.class);
manejador.muestraLista();
manejador.muestraArreglo();
manejador.muestraConjunto();
manejador.muestraMapa();
manejador.muestraPropiedades();
}
Al ejecutar nuestra aplicación obtenemos la siguiente salida:
---Mostrando lista---
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona1, edad: 26
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona2, edad: 62
class java.lang.String: Cadena
class java.lang.Integer: 5
---Mostrando arreglo---
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona2, edad: 62
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona1, edad: 26
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona Nueva, edad: 10
---Mostrando conjunto---
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona1, edad: 26
class ejemplos.spring.colecciones.beans.Persona: nombre: Persona2, edad: 62
---Mostrando mapa---
[llave] class java.lang.String: persona1, [valor]class ejemplos.spring.colecciones.beans.Persona: nombre: Persona1, edad: 26
[llave] class ejemplos.spring.colecciones.beans.Persona: nombre: Persona2, edad: 62, [valor]class java.lang.String: otra persona
[llave] class java.lang.String: sin persona, [valor]class java.lang.String: no personas
[llave] class ejemplos.spring.colecciones.beans.Persona: nombre: Persona1, edad: 26, [valor]class ejemplos.spring.colecciones.beans.Persona: nombre: Persona2, edad: 62
---Mostrando propiedades---
[llave] class java.lang.String: facebook, [valor]class java.lang.String: http://www.facebook.com/pages/Java-Tutoriales/121935157864634
[llave] class java.lang.String: pais, [valor]class java.lang.String: Mexico
[llave] class java.lang.String: nombre, [valor]class java.lang.String: Alex
[llave] class java.lang.String: sitio, [valor]class java.lang.String: http://javatutoriales.blogspot.com/
Analicemos un poco esta salida.
La primera que obtenemos es la salida de la lista. En esta, podemos comprobar que los elementos de la misma se encuentran en el mismo orden en el que los declaramos en el archivo de configuración. Primero los dos beans de tipo "Persona", después la cadena "Cadena" que declaramos como un valor, y finalmente el valor "5" que declaramos como un objeto de tipo "java.lang.Integer":
En la siguiente parte de la salida, tenemos el valor del arreglo. Aquí nuevamente, los elementos se encuentran en el mismo orden en el que los declaramos en el archivo de configuración. Tenemos primero los dos beans de tipo "Persona", y después el bean interno que declaramos, con el "nombre" de "Persona Nueva" y la "edad" de "10":
--
Posteriormente está el segmento de la salida correspondiente con el Set. Aquí vemos que aunque en el archivo de configuración declaramos 4 miembros para esta colección, al final en esta solo se insertan 2 objetos, ya que los Sets son colecciones que no permiten duplicados:
La que sigue es la salida de los elementos del mapa. Aquí podemos observar que, efectivamente, tenemos una combinación tanto de llaves como de valores de tipos "Persona" y "String", de la misma forma que en el archivo de configuración:
La última parte de la salida es la que corresponde con las propiedades. En esta, podemos ver que tanto las llaves como los valores son de tipo "String":
Como vemos, nuestras colecciones se han inyectado de forma correcta ^_^.
Tal vez algunos se hayan preguntado ¿y qué ocurre si quiero insertar una propiedad con un valor de "null", o un elemento de las colecciones como "null"? Bueno, responderemos esta pregunta en la última parte del tutorial
INYECTANDO VALORES NULOS
En casi cada situación, usaremos DI para cablear un valor constante o una referencia a un objeto dentro de una propiedad de un bean. Sin embargo en algunas ocasiones será necesario inyectar un valor null a una propiedad.Aunque en Java las referencias a objetos son por default nulas, algunas veces asumir esto no es suficiente para lograr nuestros propósitos.
Para establecer una propiedad como "null" usamos el elemento... "<null />". Por ejemplo, si quisiéramos establecer la propiedad "nombre" de un bean de tipo "Persona" como "null", lo declararíamos de la siguiente forma:
<bean id="persona1" class="ejemplos.spring.colecciones.beans.Persona">
<property name="nombre"><null /></property >
<property name="edad" value="26" />
</bean>
Y eso es todo lo que debemos hacer ^_^.
Hemos llegado al final de este tercer tutorial sobre Spring 3, espero que les sea de utilidad. No olviden dejar sus dudas, comentarios y sugerencias.
Saludos.
No hay comentarios:
Publicar un comentario