Mi granito de java: Introducción a Spring

martes, 28 de junio de 2011

Introducción a Spring

Primero voy a dar una introducción a Spring para quienes no conozcan el framework, donde veremos de que se trata, como configurarlo y un sencillo "Hola Mundo". Luego escribiré un post sobre Spring Core que permitirá conocer el framework de manera más amplia.

Spring es un marco de trabajo cuya finalidad es facilitar el desarrollo de aplicaciones con Java. Fue creado por Rod Johnson y es de código abierto.
Sus características son:
  • Simplicidad y acoplamiento débil: da la sensación que quién desarrollo Spring se imagino a Java de otra manera, más robusto y configurable, con más facilidadades y posibilidades para los desarrolladores. Esto se ve reflejado en este framework: busca ser simple y se basa en la inyección de dependencias para obtener un acoplamiento débil. Luego veremos estos dos conceptos.
  • Es un contenedor: no es solo un framewrok más. Es un contenedor que gestiona el ciclo de vida de los objetos y como se relacionan entre ellos. Proporciona una gran infraestructura que permite que el desarrollador se dedique a la lógica de la aplicación.
  • Ligero: es muy rápido en tiempo de procesamiento y no es intrusivo a la hora de desarrollar. Esto último es uno de sus puntos más fuertes.
  • Orientado a aspectos: soporta la programación orientada a aspectos, lo que permite facilitar una capa de servicios que son ideales para este tipo de programación como auditoría, o gestión de transacciones.

Módulos de Spring

Spring posee diversos módulos que se pueden agregar a las aplicaciones Java. Cada desarrollador agrega los módulos que necesite.  Spring Core es el núcleo de Spring, es el único módulo que tenemos que agregar para que Spring funcione. ya que contiene la DI (inyección de dependencias) y la configuración y uso de objetos Java. Muchas aplicaciones sólo necesitan de Spring Core sin necesidad de agregar módulos adicionales.

Otros módulos conocidos son: AOP para trabajar con aspectos, DAO para trabajar con base de datos, MVC para la capa web, Portlet MVC para trabajar con portlets, JMS para mensajería y Security para el manejo de seguridad (el framewrok de seguridad era antes conocido como Acegi).
Como se puede observar Spring nos da muchas opciones para poder agregar a nuestro proyecto. Estos no son los únicos módulos que nos ofrece Spring, sólo son los más importantes.

Inyección  de dependencias (DI).

Originalmente la inyección de dependencias se llamaba inversión de control, pero en el 2004 Martin Fowler llegó a la conclusión que realmente no se invertía el control, sino las dependencias.
La DI permite a un objeto que conozca sus dependencias mediante una interfaz y no por su implementación. De esta forma, la implementación puede variar sin que el objeto dependiente se de cuenta. La gran ventaja de la DI es el acoplamiento débil entre objetos.
Muy linda la teoría pero si uno se inicia en Spring por primera vez suena a conceptos muy abstractos.  Nada mejor que un ejemplo sencillo para aclarar los puntos. Veremos un pequeño ejemplo antes de introducirnos en Spring Core,  pero antes veremos como configurar Spring en una aplicación eclipse:

1) Bajar Spring desde http://www.springsource.org/download y agregar las fuentes al proyecto.
2) Si la distribución de Spring no adjunta las librerías de apache commons también hay que bajarlas: http://commons.apache.org/
Adjunto un pic con las librerias necesarias para empezar (ignoren el archivo spring.xml por ahora):


3) Dentro de las librerías habrán visto que hay un archivo llamado spring.xml (le pueden poner el nombre que quieran, es lo mismo).
Por ahora les recomiendo que hagan un archivo xml que tenga el siguiente contenido y lo agreguen al classpath. Luego les explicaré que significa cada cosa de dicho archivo.


<?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-2.0.xsd">

<bean id="saludoImpl" class="saludo.SaludoImpl">
      <property name="valor" value="Hola mundo!"/>
</bean>

<bean id="alumno" class="saludo.Alumno" >
      <property name="saludo" ref="saludoImpl"/>
</bean>

</beans>

4) Por último, vamos a hacer una clase que nos permita levantar el archivo:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class ContextFactory {
   
    private static ApplicationContext respuesta;
   
   
    public static ApplicationContext getInstance(){
        if (respuesta != null) {
            return respuesta;
        }
        respuesta = new FileSystemXmlApplicationContext
        ("C:/Users/max/eclipse workspace/spring.xml"); // aca pongan la ruta donde pusieron el xml
        return respuesta;
    }

Listo, con esto tenemos todo para comenzar con nuestro ejemplo.
Crearemos una clase Alumno que tiene un atributo de la clase (intefaz) Saludo.


Aquí una posible implementación de la clase Saludo:

Veamos como se ejecuta esto:


¿Que ha pasado aquí?

A simple vista deduciremos lo siguiente: la clase Alumno posee un atributo que es una interfaz y no se entera como es la implementación de la misma.
Vamos a explicar el funcionamiento: todo se debe gracias al archivo de configuración xml. El tag <beans> es el elemento raíz del xml y todo lo que se encuentre dentro de este elemento es configuración de Spring.
El elemento <bean>  indica a Spring que se configurará un objeto para ser utilizado en el contenedor de Spring. Id es un atributo obligatorio que debería identificar unívocamente al bean en cuestión.
En nuestro ejemplo vemos la siguiente configuración:
<bean id="saludoImpl" class="saludo.SaludoImpl">
<property name="valor" value="Hola mundo!"/>
</bean>
El atributo class indica la clase a la cual pertenece el bean y cada bean puede tener subelementos <property> que representan los atributos (en este caso me refiero a atributos de objetos y no de xml) del bean. El name debe coincidir con el nombre de atributo que tenga en la clase y, en este ejemplo, value sería el valor que toma. Veremos luego que hay varias opciones más.
Continuando con el xml vemos:
<bean id="alumno" class="saludo.Alumno" >
<property name="saludo" ref="saludoImpl"/>
</bean>
La novedad aca aplica a atributo ref del elemento property: esta indicando que este atributo es un objeto y, por lo tanto, es conveniente configurar dicho objeto de manera separa y se hace referencia al mismo mediante su id.

¿Y no es lo mismo hacerlo así?


Si y no a la vez: tradicionalmente cada objeto es responsable de obtener sus propias dependencias y esto lleva a un código muy acoplado. Cada objeto debe conocer como se construyen otros y si bien los patrones creacionales pueden ayudar con este tema, entonces hay que conocer que patrón se aplicó a cada objeto.
Cuando se aplica la DI se otorgan las dependencias a cada objeto, se obtiene un acoplamiento débil: si un obejto solo conoce sus dependencias mediante su interfaz, entonces puede variar su implementación sin que  el objeto dependiente sepa la diferencia. Por otro lado, el código es más limpio y ordenado.

Hasta aquí con esta breve introducción a Spring. Cuando escriba sobre Spring Core se verán estos temas con más profuncidad.

3 comentarios:

Anónimo dijo...

¡Excelente artículo!

Max dijo...

Muchas gracias!

apuntesJavaWeb dijo...

Excelentes tutoriales, demaciado buenos.