J2ee, Spring

Introducción a los aspectos básicos de Spring Framework – Primera Parte

springframework

1.- Introducción a Spring

  • EL objetivo de Spring

– Proveer el soporte  para desarrollar aplicaciones empresariales con java.

– Enfocarnos en resolver nuestro problema de dominio.

  • El rol en la arquitectura de aplicaciones empresariales.

– El core de Spring nos da la posibilidad de configurar nuestra aplicación de maneras sencillas,así  también el de poder realizar una integración con aplicaciones empresariales,  realizar testing y poder manejar el acceso a la data.

– Permite integrar y configurar componentes de manera sencilla; parte de los componentes son  plain java objects.

– Integrar pool de conexiones  de base de datos, transacciones, seguridad, messaging, acceso remoto, entre otras.

– Realizar testing,  desacoplando  los objetos desde nuestros ambientes(testing, producción) , realizar test unitarios o de integración.

– El acceder a la data de una manera mucho mas fácil, spring  nos entrega soporte para la gran parte de las tecnologías de acceso de datos, como lo son JDBC,JPA,JDO,HIBERNATE,IBATIS, ya ahora llamado MyIbatis, otra característica es que maneja los recursos por nosotros, un ejemplo de esto es que puede adquirir la conexión, participar en la transacción, manejar las exceptions, procesar resultados, etc; nos provee de helpers como lo es JdbcTemplate.

– Soporte para el desarrollo de aplicaciones Web, permite la integración con JSF, Struts, Velocity, FreeMaker y algunos otros, nos permite trabajar con el patrón de diseño MVC, rendear las vistas,validación de formularios, manejo de estados con web flow,  acciones de usuarios, etc, así también, aplicar una capa de seguridad con spring Security.

– Soporte en el desarrollo de aplicaciones empresariales,  desarrollando webservices,  asegurando servicios con accesos de control, planificando jobs y procesos, integrando servicios de mensajería.

  • La base de spring se puede definir mediante el triangulo de Spring

– Inyección de dependencia

– Programacion orientada a aspectos

-y Abstracción de servicios empresariales.

2 .- Beans y contenerdores:

  • En Spring un bean es un objeto que vive y que es manipulado por el contenedor, no confundir con un javabean.
  • Spring gestiona todo el ciclo de vida de la aplicación, todos los beans son inicializados antes que se utilicen.
  • Los beans siempre son creados en orden correcto, Spring se encarga de resolver la dependencia de cada uno de ellos.
  • Cada bean posee un identificador único
  • Encapsula las implementaciones dado  el despliegue de la aplicación, oculta los detalles de la implementación.

2.1 – Los beans.

Un bean es un objeto, y como tal puede ser bastante simple,  como el siguiente:

Con sus atributos, getters y setters, tal y cual, es un objeto plano en java, para pasarlo a un bean de Spring, tenemos que ponerlo en un contenedor de beans, que no es mas que una definición en un archivo xml.

Esta es una clase que no contiene dependencias, si quisiéramos instanciar la clase vía reflection, bastaría con hacer:

SimpleBean simpleBean = new SimpleBean();

Pero Spring nos provee de una interfaz para proporcionar la configuración de una aplicación, esta es el ApplicationContext.

ApplicationContext context = new ClassPathXmlApplicationContext(“basic-context.xml”);
SimpleBean simpleBean = (SimpleBean) context.getBean("simpleBean",SimpleBean.class);

Ahora Spring es quien contiene y maneja todo el ciclo de vida del bean llamado «simpleBean» que definimos mas arriba.

2.2 Inyección de dependencias.

Spring nos permite el poder inyectar dependencias a nuestros beans vía setter, o constructor.

2.2.1 Inyección de dependencia por constructor.

Es equivalente a:

SimpleBean sb = new SimpleBean(787545, "valor del tipo string", new HashMap...);

Beneficios de la inyección por constructor:

  1. Cumplir con las dependencias obligatorias.
  2. Proveer de inmutabilidad
  3. Programar de una forma consistente, creación e inyección en una sola linea de código.

2.2.2 Inyección de dependencia por Setter.

Es equivalente a:

SimpleBean sb = new SimpleBean();
sb.setId(787545);
sb.setName("valor del tipo string");
sb.setMaps(new HashMap()...);

Beneficios de la inyección por Setter:

  1. Permitir dependencias por defecto u opcionales.
  2. Tener nombres descriptivos.
  3. Seguir la convención JavaBeanTM
  4. Se hereda de forma automática.

También se pueden combinar.

Los puristas prefieren uno sobre otro,¿Cual usar?,  tu elijes, se consistente…

2.2.3 Dependencias y configuración en detalle ver aqui

En resumen, dentro de los beneficios de las inyecciones de dependencia podemos mencionar.

  • Al objeto se le entrega lo necesario para trabajar, simplifica el código, permite la reutilización, permite resolver la dependencias entre los componentes.
  • Nos permite trabajar con interfaces, para ocultar los detalles de la implementación
  • Promueve las pruebas de manera aislada o de todos los componentes juntos.
  • Maneja el ciclo de vida del objeto.

3.- El Factory Bean

El factoryBean es una interfaz que es implementada por los objetos que usara el BeanFactory,  si un objeto la implementa, este se utilizará como  una fabrica de objeto, esta interfaz soporta  scopes singletons y prototypes, con la opción de crearse en forma temprana o tardía(lazily).
Métodos de FactoryBean:
getObject() retorna una instancia del objeto creado.
getObjectType() retorna el tipo de objeto que se creo, o null si no se conoce.
isSingleton() si el objeto es manejado como un singleton.

A tener en cuenta:

  • Spring autodetecta cualquier implementación del factoryBean y retorna el objeto creado por
    el metodo getObject()
  • Nos permite encapsular la creación del objeto
  • Spring nos permitirá instanciar el objeto como un bean Singleton, o Prototype.

3.1 Implementando FactoryBean:

Objeto que implementa FactoryBean

package com.spring.basic.factory;

import org.springframework.beans.factory.FactoryBean;

/**
 * Clase de muestra de como funciona el facoryBean de spring
 * <ul>
 * 	<li>Spring autodetecta  cualquier implementacion del {@link FactoryBean } y retorna el objeto creado por
 * el metodo <code>getObject()</code></li>
 * <li>Nos permite encapsular la creacion del objeto</li>
 * <li>Spring nos permitira dejarlo como un bean Singleton</li>
 * </ul>
 * @author jbovet
 */
public class ObjectFactory implements FactoryBean {

	/***
	 * Objeto que sera devuelto
	 */
	private MockObject mockObject;

	private Integer idMock;
	private String nameMock;
	private boolean isSingleton = Boolean.TRUE;

	/***
	 * retorna la instancia del objeto MockObject
	 */
	public Object getObject() throws Exception {
		if (mockObject ==null) {
			initMockObject();
		}
		return mockObject;
	}

	/***
	 * crea la instancia del objeto
	 */
	private void initMockObject() {
		//se crea el objeto mediante constructor
		mockObject = new MockObject(nameMock,idMock);
	}

	/***
	 * Obtiene la clase del objeto
	 */
	public Class<MockObject> getObjectType() {
		return MockObject.class;
	}

	/**
	 * el factorybean se registra como singleton
	 * @see org.springframework.beans.factory.FactoryBean#isSingleton()
	 */
	public boolean isSingleton() {
		return isSingleton;
	}

	public void setIdMock(Integer idMock) {
		this.idMock = idMock;
	}
	public void setNameMock(String nameMock) {
		this.nameMock = nameMock;
	}
}

Configuración del contexto de Spring, para la implementación de un objeto que implementa el FactoryBean.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

	<bean id="mockObjectFactory" class="com.spring.basic.factory.ObjectFactory">
		<property name="idMock" value="123"/>
		<property name="nameMock" value="mockito"/>
	</bean>
        <!--bean que usa el objeto mock -->
	<bean id="simpleBean">
	    <property name="mockObject" ref="mockObjectFactory"/>
	</bean>
</beans>

Test para obtener el objeto MockObject

package com.spring.basic.factory;

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

public class TestFactory {

	public static void main(String[] args) throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/spring/basic/factory/factory-context.xml");
		MockObject mockObject = (MockObject) context.getBean("mockObjectFactory");
		System.out.println(mockObject.toString());
		//SimpleBean sb = (SimpleBean) context.getBean("simpleBean", SimpleBean.class);
		//sb.doSomething();
	}
}

El uso de los FactoryBeans en Spring:

  • JndiObjectFactoryBean: para poder trabajar con objetos JNDI
  • Nos permite crear proxies remotos
  • Para configurar el acceso a la data.(ibatis, hibernate,jpa,etc)

4.- Creando un Spring Application Context

Un Spring Application Context puede ser ejecutado en casi cualquier ambiente, incluyendo en sistema de testing como Junit, dentro de una aplicacion web, con EJB’s, o e una aplicación  standalone de java, podemos cargar el contexto de partes, como lo es el classpath, desde el sistema de archivos, o como un recurso dentro de una aplicion web, para esto, spring nos proporciona 3 implementaciones para cargar nuestros beans.

Tipo Ejemplo
ClassPathXmlApplicationContext $CLASSPATH/org/spring/basic/application-config.xml
FileSystemXmlApplicationContext \tmp\context\application-config.xml
XmlWebApplicationContext $JBOSS_HOME/webapp/webappName/WEB-INF/application-config.xml

4.1 Usando prefijos.

classpath:

new ClassPathXmlApplicationContext(“classpath:org/spring/basic/application-config.xml”);

file:

new FileSystemXmlApplicationContext(“file:\tmp\context\application-config.xml”);

http:

ctx.getResource("http://myserver/logo.png);

Los prefijos los podemos utilizar en cualquier lugar donde spring necesite cargar algún recurso, no solamente como  argumento en el constructor del applicationContext.

4.2  Creando mutiples Application Context.

  • Un contexto puede ser configurado desde múltiples archivos, permite separar la definición de los beans en grupos lógicos.
  • Una buena practica es separar los beans de la aplicación de los  de infraestructura, ya que estos últimos pueden cambiar dependiendo del entorno.

Ejemplo de como cargar los beans de producción con mysql

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
“app-config.xml”,
“mysql-infrastructure-config.xml”
});

Ejemplo de como cargar los beans de desarrollo con mysql en test

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
“app-config.xml”,
“mysql-test-infrastructure-config.xml”
});

En la segunda parte, veremos mas en profundidad el ciclo de vida de un bean..

Estándar