Spring Tutorial v0
Spring Tutorial v0
29/12/2004
Tutorial Spring
1 Introducción. ........................................................................................ 4
1.1 ¿Qué es Spring?.................................................................................4
1.2 ¿Que proporciona? .............................................................................5
1.3 ¿Qué es Ioc? .....................................................................................7
2 Herramientas necesarias. ..................................................................... 8
3 Primer ejemplo de uso .......................................................................... 8
3.1 Librerias necesarias............................................................................9
3.2 La estructura de directorios .................................................................9
3.3 Configurando LOG4J ...........................................................................9
3.4 Programando nuestra clase. .............................................................. 10
3.5 Configuración de Spring. ................................................................... 11
3.6 Clases de test.................................................................................. 11
3.7 Programando implementación alternativa. ........................................... 12
4 Segundo ejemplo. ............................................................................... 13
4.1 Creacion de base de datos................................................................. 13
4.2 Configurando Hibernate .................................................................... 13
4.3 Programando clases de negocio. ........................................................ 14
4.4 Modificando configuración. ................................................................ 15
4.5 Ejecución. ....................................................................................... 16
5 Spring AOP ......................................................................................... 16
5.1 ¿Qué es AOP? .................................................................................. 16
5.2 Ejemplo de AOP. .............................................................................. 17
5.3 Modificando Configuración. ................................................................ 17
5.4 Ejecución. ....................................................................................... 18
6 Tercer ejemplo.................................................................................... 19
6.1 Transacciones.................................................................................. 19
6.2 Programando clases sin trasnsacciones ............................................... 19
6.3 Modificando Configuración ................................................................. 21
6.4 Ejecución. ....................................................................................... 22
6.5 Conclusiones ................................................................................... 22
7 Spring MVC ......................................................................................... 22
7.1 ¿Qué es MVC? ................................................................................. 22
1 Introducción.
La meta a conseguir es separar los accesos a datos y los aspectos relacionados con
las transacciones, para permitir objetos de la capa de negocio reutilizables que no
dependan de ninguna estrategia de acceso a datos o transacciones.
Spring ofrece una manera simple de implementar DAOs basados en Hibernate sin
necesidad de manejar instancias de sesion de Hibernate o participar en
transacciones. No necesita bloques “try-catch”, innecesario para el chequeo de
transacciones. Podríamos conseguir un método de acceso simple a Hibernate con
una sola línea.
Spring proporciona:
¾ Una potente gestión de configuración basada en JavaBeans, aplicando los
principios de Inversión de Control (IoC). Esto hace que la configuración de
aplicaciones sea rápida y sencilla. Ya no es necesario tener singletons ni
ficheros de configuración, una aproximación consistente y elegante. Estas
definiciones de beans se realizan en lo que se llama el contexto de aplicación.
¾ Una capa genérica de abstracción para la gestión de transacciones,
permitiendo gestores de transacción añadibles (pluggables), y haciendo
sencilla la demarcación de transacciones sin tratarlas a bajo nivel. Se incluyen
estrategias genéricas para JTA y un único JDBC DataSource. En contraste con
el JTA simple o EJB CMT, el soporte de transacciones de Spring no está atado
a entornos J2EE.
¾ Una capa de abstracción JDBC que ofrece una significativa jerarquía de
excepciones (evitando la necesidad de obtener de SQLException los códigos
que cada gestor de base de datos asigna a los errores), simplifica el manejo
de errores, y reduce considerablemente la cantidad de código necesario.
¾ Integración con Hibernate, JDO e iBatis SQL Maps en términos de soporte a
implementaciones DAO y estrategias con transacciones. Especial soporte a
Hibernate añadiendo convenientes características de IoC, y solucionando
muchos de los comunes problemas de integración de Hibernate. Todo ello
cumpliendo con las transacciones genéricas de Spring y la jerarquía de
excepciones DAO.
Estos puntos son suficientes y necesarios para poder hablar de una definición
básica de IoC. Spring proporciona un contenedor que maneja todo lo que se hace
con los objetos del IoC. Debido a la naturaleza del IoC, el contenedor más o menos
ha definido el ciclo de vida de los objetos. Y, finalmente, el contenedor resuelve las
dependencias entre los servicios que él controla.
2 Herramientas necesarias.
Para poder realizar los siguientes ejemplos necesitaremos varias librerias. Para
facilitar la ejecución recomiendo tener instalado un ide de desarrollo java como
eclipse o netBeans para poder navegar por el código con soltura. En el caso
concreto de este documento recomiendo usar eclipse, puesto que es el el IDE que
usaré para compilar y ejecutar
Para el conjunto de los ejemplos necesitaremos las librerias:
¾ Spring – en http://www.springframework.org existe un fichero
“Springframework-whith-dependences.zip” que contiene todas las clases
necesarias para ejecutar todas las herramientas de spring.
¾ Log4j – En el fichero anterior encontramos el jar necesario.
¾ Jakarta Common-logging – Lo mismo ocurre con esta librería.
¾ Hibernate – Podemos encontrarlo en su pagina web.
¾ Struts – Podremos localizarlo en la pagina de jakarta-struts.
¾ JUnit – Podemos encontrar las clases en el fichero de spring-with-
dependences. En caso contrario las librerias las podemos encontrar en su sitio
web. Si se usa eclipse como ide lo incluye.
Hasta ahora solo hemos visto la teoría de que es el framework Spring. Ahora vamos
a realizar un ejemplo sencillo, muy básico para simular el uso de la capa de
configuración de beans, el núcleo básico de Spring, para poder posteriormente ir
añadiendo funcionalidades a la aplicación.
En este ejemplo no necesitaremos base de datos, simularemos los accesos a base
de datos con una clase que devuelva unos datos constantes. Después intentaremos
sustituir esta clase de datos por un acceso a Hibernate, para, posteriormente,
incluir transacciones.
Para el desarrollo de este ejemplo usaremos JUNIT para el proceso de test de las
clases, se podría usar una clase main(), pero se ha considerado más adecuado
introducir JUNIT por las posibilidades de test que ofrece.
Para nuestro uso personal vamos a configurar log4j para que nos vaya dejando
trazas. El fichero será el siguiente.
log4j.rootCategory=INFO, Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=(%-35c{2} %-4L) %m%n
log4j.logger.paquete=ALL
Con este fichero, que colocaremos en la raiz de nuestra carpeta fuente (src), nos
mostrara todas nuestras trazas en la consola.
}
Con estas clases realizamos una primera implementación de acceso a datos. Esta
clase almacena los datos en una clase interna de almacenamiento:
public class UsuarioDaoStatic implements UsuarioDao {
private static final Log log = LogFactory.getLog(UsuarioDaoStatic.class);
Esta seria una forma normal de cualquier aplicación que accede a una capa de
acceso a datos. Ahora configuraremos Spring para que cada vez que se solicite
acceso al interfaz UsuarioDao se haga mediante la implementación que nosotros
deseamos.
Para este primer ejemplo, bastante básico, debemos de configurar Spring para que
al solicitar el bean UsuarioDao, en este fichero es donde le especificamos la
implementación concreta.
El fichero lo llamaremos applicationContext.xml y tendrá como contenido:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-
beans.dtd">
<beans>
<bean id="usuarioDao" class="paquete.dao.impl1.UsuarioDaoStatic" />
</beans>
Ahora vamos a ver como se combinan en un uso normal. Para ello crearemos una
clase TestUsuarioDao. El código es el siguiente:
public class TestUsuarioDao extends TestCase {
private ClassPathXmlApplicationContext ctx;
private UsuarioDao dao;
private Usuario usuario;
private static final Log log = LogFactory.getLog(TestUsuarioDao.class);
}
public static void main (String[] args)
{
junit.textui.TestRunner.run(TestUsuarioDao.class);
}
}
El test lo podemos realizar usando el interfaz gráfico que proporciona eclipse o
directamente desde la linea de comando. En cualquier caso, en la salida de la
consola obtenemos:
(test.TestUsuarioDao 48) SETUP del test
(impl1.UsuarioDaoStatic 46) Constructor de la implementacion DAO
(test.TestUsuarioDao 52) hemos obtenido el objeto que implementa usuarioDao
(impl1.UsuarioDaoStatic 51) Guardamos el usuario paquete.modelo.Usuario@15212bc
(impl1.UsuarioDaoStatic 57) Estamos buscando usuario 1
(impl1.UsuarioDaoStatic 62) Borramos el usuario 1
(impl1.UsuarioDaoStatic 57) Estamos buscando usuario 1
Para probar el cambio de una implementación sin tener que modificar ni una sola
línea de código haremos lo siguiente. Creamos una nueva clase que llamaremos
UsuarioDaoOtraImpl que para ahorrar tiempo tendrá el mismo contenido que
UsuarioDaoStatic , solo que lo situaremos en otro paquete, de forma que la
estructura total de nuestro proyecto quede.
NOTA: Existe un método .refresh() que nos permite recargar el fichero de configuración haciendo
una llamada a este metodo. Es decir, que se podria cambiar de implementacion (por ejemplo de
acceso con Hibernate a otro tipo de acceso ) “en caliente”.
4 Segundo ejemplo.
El ejemplo anterior es sólo una pequeña muestra de cómo se puede usar Spring,
las posibilidades sólo se dejan intuir con este ejemplo. Con el siguiente vamos a
intentar que nuestra aplicación de ejemplo anterior, usando Spring se conecte a
base de datos mediante Hibernate.
Para poder Realizar este proceso vamos a procurar realizar la menor cantidad de
modificaciones en el código anterior, para así apreciar el proceso de integración de
Spring, que se anuncia como no intrusivo.
Hay que considerar que la creación de una base de datos usando MySql, HSQLDB,
Oracle o cualquier otro método se escapa de la finalidad de este documento. Solo
comentar que para mi ejemplo concreto usé MySQL.
El script de creación de la tabla es el siguiente.
CREATE TABLE `atril`.`USUARIO` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(45) NOT NULL,
PRIMARY KEY(`id`)
)
TYPE = InnoDB;
import java.util.List;
import org.springframework.orm.hibernate.HibernateTemplate;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
import paquete.dao.UsuarioDao;
import paquete.modelo.Usuario;
// Extiende de una clase que proporciona los métodos necesarios para acceder a Hibernate
public class UsuarioDaoHibernate extends HibernateDaoSupport implements
UsuarioDao {
}
}
Esta será la implementación de acceso a Hibernate, que sustituye a las
implementaciones hechas anteriormente. Como se puede comprobar extiende de
HibernateDaoSupport, una clase que Spring proporciona para facilitar la integración
con Hibernate.
<property name="url"><value>jdbc:mysql://localhost/atril</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value>root</value></property>
</bean>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.pool_size">1</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
</beans>
4.5 Ejecución.
5 Spring AOP
AOP son las siglas en ingles de Programación orientada al aspecto (Aspect Oriented
Programming).
La definición más simple de AOP es “una manera de eliminar codigo duplicado”.
Java es un lenguaje orientado a objetos y permite crear aplicaciones usando una
determinada jerarquía de objetos, sin embargo esto no permite una manera simple
de eliminar código repetido en aquellos objetos que no pertenecen a la jerarquía.
AOP permite controlar tareas.
En el siguiente ejemplo modificaremos nuestra aplicación para permitir que se
ejecuten tareas de escritura de trazas adicionales, que nos servirá para comprender
el mecanismo de AOP, para poder ampliar luego nuevas funcionalidades, como
transacciones.
En AOP usaremos conceptos como interceptor, que inspeccionará el codigo que se
va a ejecutar, permitiendo por lo tanto realizar ciertas acciones como : escritura de
}
Spring proporciona una clase ya implementada para realizar esta operación, entre
otros interceptores ya implementados. Se recomienda un vistazo a la API de Spring
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- DEfinimos la clase de proxy que carga la implementacion -->
<bean id="usuarioDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>paquete.dao.UsuarioDao</value></property>
<property name="target"><ref local="usuarioImpl"/></property>
<!-- Definimos los interceptores del bean -->
<property name="interceptorNames">
<list><value>interceptor</value></list>
</property>
</bean>
5.4 Ejecución.
6 Tercer ejemplo.
6.1 Transacciones.
Siguiendo con los ejemplos de AOP vamos a añadir a nuestra aplicación control de
transacciones, de forma que podamos controlar, en caso de excepción, un
“rollback” de la transacción realizada.
Tradicionalmente en las transacciones es necesario un método tx.begin(),
tx.commit() y tx.rollback() (o nombres similares), la idea es forzar las
transacciones con AOP sin necesidad de insertar estas llamadas en el código,
controlando así cuando realizar transacciones y cuando no.
}
Este método pretende realizar el proceso de inserción masiva de usuarios en la
Base de datos. Al modificar el interface debemos modificar la clase de Hibernate
que la implementa. Este método será:
public void saveListaUsuarios (Usuario[] usuario) {
}
Como se puede apreciar el proceso guarda cada uno de los usuarios a añadir.
Hibernate lo tenemos configurado de forma que debemos de asignarle nosotros a
mano el ID del usuario, por lo que un campo null en este valor provocará una
excepción.
Para apreciar este efecto vamos a modificar nuestra clase de TEST añadiendo el
siguiente método de test:
/**
* Realiza el test de inserción de datos malos que provoquen un efecto
* de rollback en las transacciones.
* @throws Exception excepción generada.
*/
public void testTransaccion () throws Exception
{
log.debug("Iniciamos guardar todos los usuarios:");
Usuario[] usuarios = this.ListadoUsuariosMalos ();
log.debug (usuarios);
try {
dao.saveListaUsuarios(usuarios);
} catch (Exception e)
{
log.error (e);
List listado = dao.listAll();
log.debug ("La lista debe de estar vacia");
assertTrue(listado.isEmpty());
}
/**
* @return Un listado de usuarios con algunos datos malos
*
*/
private Usuario[] ListadoUsuariosMalos () {
ID Nombre
101 Nombre 2
Es decir, que nos ha insertado los dos primeros datos. En algunos casos esto no es
deseable, es por lo que deberiamos de iniciar un proceso de transacción y hacer un
rollback () en caso de excepción.
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.connection.pool_size">1</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
<bean id="usuarioDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="usuarioDaoTarget"/></property>
<property name="transactionAttributes">
<!-- define the transaction specs here -->
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="preInterceptors"><ref local="interceptor" /></property>
</bean>
</beans>
6.4 Ejecución.
6.5 Conclusiones
PENDIENTE
7 Spring MVC
PENDIENTE
PENDIENTE
PENDIENTE
PENDIENTE
PENDIENTE
PENDIENTE
7.7 Ejecutando.
PENDIENTE
7.8 Conclusiones.
PENDIENTE
8 Conclusiones
8.1 Ventajas
8.2 Inconvenientes