2. Artículo 1 - Spring IoC
Objetivos del documento:
- descubrir las posibilidades de configuración e integración del marco Spring (http://www.springframework.org)
- definir y utilizar el concepto de IoC (Inversión de control), también conocido como inyección de dependencias (Dependency Injection)
2.1. Configurar una aplicación de tres capas con Spring
Consideremos una aplicación clásica de tres capas:
![]() |
Supondremos que el acceso a las capas de negocio y DAO está controlado por interfaces de Java:
- la interfaz [IArticlesDao] para la capa de acceso a datos
- la interfaz [IArticlesManager] para la capa de negocio
En la capa de acceso a datos o capa DAO (Data Access Object), es común trabajar con un SGBD y, por lo tanto, con un controlador JDBC. Consideremos el esqueleto de una clase que accede a una tabla de artículos en un SGBD:
Para realizar una operación en el SGBD, cualquier método necesita un objeto [Connection] que represente la conexión a la base de datos, a través de la cual transitarán los intercambios entre esta y el código Java. Para construir este objeto, se necesitan cuatro datos:
el nombre de la clase del controlador JDBC del SGBD | |
la URL de la base de datos que se va a utilizar | |
la identidad con la que se establece la conexión | |
la contraseña de esta identidad |
¿Cómo puede nuestra clase [ArticlesDaoPlainJdbc] anterior obtener esta información? Existen varias posibilidades:
solución 1: la información está codificada de forma estática en la clase:
La desventaja de esta solución es que hay que modificar el código Java cada vez que se produce un cambio en esta información, por ejemplo, al cambiar la contraseña.
Solución 2: la información se transmite al objeto al momento de su construcción:
Aquí, el objeto recibe, al crearse, la información que necesita para funcionar. El problema se traslada entonces al código que le transmitió los cuatro datos. ¿Cómo los obtuvo? La siguiente clase [ArticlesManagerWithDataBase] de la capa de negocio podría crear un objeto [ArticlesDaoPlainJdbc] de la capa de acceso a datos:
![]() |
Se observa que, una vez más, la información necesaria para la construcción del objeto [ArticlesDaoPlainJdbc] se le proporciona al constructor del objeto [ArticlesManagerWithDataBase]. Podemos imaginar que esta información le es transmitida por una capa superior, como la capa de interfaz con el usuario. De esta manera, paso a paso, llegamos a la capa más alta de la aplicación. Debido a su posición, esta no es llamada por ninguna capa que pueda transmitirle la información de configuración que necesita. Por lo tanto, es necesario encontrar una solución alternativa a la configuración mediante el constructor. La solución habitual para configurar una aplicación en su capa más alta es utilizar un archivo que contenga toda la información susceptible de cambiar con el tiempo. Puede haber varios archivos de este tipo. Al iniciar la aplicación, una capa de inicialización creará entonces todos o parte de los objetos necesarios para las diferentes capas de la aplicación.
Existe una gran variedad de archivos de configuración. La tendencia actual es utilizar archivos XML. Esta es la opción elegida por Spring. El archivo que configura un objeto [ArticlesDaoPlainJdbc] podría ser el siguiente:
Una aplicación es un conjunto de objetos que Spring denomina «beans», ya que siguen la norma JavaBean para nombrar los accesores e inicializadores (getters/setters) de los campos privados de un objeto. Los objetos que, en una aplicación, tienen la función de prestar un servicio, suelen crearse en una sola instancia. Se les llama singletons. Así, en nuestro ejemplo de aplicación de múltiples capas que estamos analizando aquí, el acceso a la base de datos de artículos estará a cargo de un único ejemplar de la clase [ArticlesDaoPlainJdbc]. En una aplicación web, estos objetos de servicio atienden a varios clientes al mismo tiempo. No se crea un objeto de servicio por cada cliente.
El archivo de configuración de Spring anterior permite crear un único objeto de servicio de tipo [ArticlesDaoPlainJdbc] en un paquete llamado [istia.st.articles.dao]. Los cuatro datos necesarios para el constructor de este objeto se definen dentro de una etiqueta <bean>...</bean>. Habrá tantas etiquetas <bean> como singletons se deban construir.
¿En qué momento se llevará a cabo la construcción de los objetos definidos en el archivo de Spring? La inicialización de una aplicación puede delegarse al método main de esa misma aplicación, si es que cuenta con uno. En el caso de una aplicación web, podría ser el método [init] del servlet principal. En toda aplicación hay un método que, con certeza, será el primero en ejecutarse. Por lo general, es en este donde se lleva a cabo la construcción de los singletons.
Veamos un ejemplo. Supongamos que queremos probar la clase [ArticlesDaoPlainJdbc] anterior mediante una prueba JUnit. Una clase de prueba JUnit cuenta con un método [setUp] que se ejecuta antes que cualquier otro método. Es ahí donde se creará el singleton [ArticlesDaoPlainJdbc].
Si seguimos la solución de pasar la información de configuración mediante el constructor, tendremos la siguiente clase de prueba:
La clase de llamada [TestArticlesPlainJdbc] debe conocer los cuatro datos necesarios para la inicialización del singleton [ArticlesDaoPlainJdbc] que se va a construir.
Si seguimos la solución de pasar la información de configuración mediante un archivo de configuración, podríamos tener la siguiente clase de prueba utilizando el archivo de Spring descrito anteriormente.
En este caso, la clase de llamada [TestSpringArticlesPlainJdbc] no necesita conocer la información necesaria para la inicialización del singleton que se va a construir. Solo necesita saber:
- [springArticlesPlainJdbc.xml]: el nombre del archivo de configuración de Spring descrito anteriormente
- [articlesDao]: el nombre del singleton que se va a crear
Cualquier modificación en el archivo de configuración, fuera de estas dos entidades, no tiene ningún impacto en el código Java. Este método de configuración de los objetos de una aplicación es muy flexible. Para configurarse, la aplicación solo necesita saber dos cosas:
- el nombre del archivo de Spring que contiene la definición de los singletons que se deben crear
- los nombres de estos singletons, que el código Java utiliza para obtener una referencia a los objetos a los que se han asociado gracias al archivo de configuración
2.2. Inyección de dependencias e inversión de control
Introduzcamos ahora el concepto de inyección de dependencias (Dependency Injection) que utiliza Spring para configurar las aplicaciones. También se utiliza el término inversión de control (IoC, Inversion of Control). Consideremos la creación del singleton [ArticlesManagerWithDataBase] de la capa de negocio de nuestra aplicación:
![]() |
Para acceder a los datos del SGBD, la capa de negocio debe utilizar los servicios de un objeto que implemente la interfaz [IArticlesDao], por ejemplo, un objeto de tipo [ArticlesDaoPlainJdbc]. El código de la clase [ArticlesManagerWithDataBase] podría verse así:
public class ArticlesManagerWithDataBase implements IArticlesManager {
// una instancia de acceso a datos
private IArticlesDao articlesDao;
....
public ArticlesManagerWithDataBase (String driverClassName, String url, String user, String pwd, ...) {
...
// creación del servicio de acceso a datos
articlesDao =(IArticlesDao)new ArticlesDaoPlainJdbc(driverClassName,url,user,pwd);
...
}
public ... doSomething(...){
...
}
}
Se supone que la clase [ArticlesDaoPlainJdbc] implementa aquí una interfaz [IArticlesDao]:
Para crear el singleton de tipo [IArticlesDao] necesario para el funcionamiento de la clase, el constructor de esta utiliza explícitamente el nombre de la clase de implementación de la interfaz [IArticlesDao]:
Por lo tanto, existe una dependencia rígida en el código respecto al nombre de la clase. Si la clase de implementación de la interfaz [IArticlesDao] llegara a cambiar, habría que modificar el código del constructor anterior. Existen las siguientes relaciones entre los objetos:
![]() |
La clase [ArticlesManagerWithDataBase] toma por sí misma la iniciativa de crear el objeto [ArticlesDaoPlainJdbc] que necesita. Volviendo al término «inversión de control», se diría que es ella quien tiene el «control» para crear el objeto que necesita.
Si tuviéramos que escribir una clase de prueba JUnit para la clase [ArticlesManagerWithDataBase], podríamos tener algo como lo siguiente:
La clase de prueba crea una instancia de la clase de negocio [ArticlesManagerWithDataBase], la cual, a su vez, crea en su constructor una instancia de la clase de acceso a datos [ArticlesDaoPlainJdbc].
La solución con Spring eliminará la necesidad de que la clase de negocio [ArticlesManagerWithDataBase] conozca el nombre [ArticlesDaoPlainJdbc] de la clase de acceso a datos que necesita. Esto permitirá cambiarlo sin modificar el código Java de la clase de negocio. Spring permitirá crear al mismo tiempo los dos singletons: el de la capa de acceso a datos y el de la capa de negocio. El archivo de configuración de Spring definirá un nuevo bean:
La novedad radica en el bean que define el singleton de la clase de negocio que se va a crear:
<bean id="articlesManager" class="istia.st.articles.domain.ArticlesManagerWithDataBase">
<property name="articlesDao">
<ref bean="articlesDao"/>
</property>
</bean>
- Se define la clase que implementa el bean [articlesManager]: [ArticlesManagerWithDataBase]
- el campo [articlesDao] del bean recibe un valor mediante la etiqueta <property name="articlesDao">. Se trata del campo definido en la clase [ArticlesManagerWithDataBase]:
Para que Spring pueda inicializar el campo [articlesDao] mediante su etiqueta <property>, el campo debe cumplir con la norma JavaBean y debe existir un método [setArticlesDao] para inicializar el campo [articlesDao]. Cabe destacar que el nombre del método se deriva de manera muy precisa del nombre del campo. Paralelamente, suele existir un método [get...] para obtener el valor del campo. En este caso, es el método [getArticlesDao]. En esta nueva versión, la clase [ArticlesManagerWithDataBase] ya no tiene constructor. Ya no lo necesita.
- El valor que Spring asignará al campo [articlesDao] es el del bean [articlesDao] definido en su archivo de configuración:
<bean id="articlesManager" class="istia.st.articles.domain.ArticlesManagerWithDataBase">
<property name="articlesDao">
<ref bean="articlesDao"/>
</property>
</bean>
<bean id="articlesDao" class="istia.st.articles.dao.ArticlesDaoPlainJdbc">
<constructor-arg index="0">
.............
</bean>
- Cuando Spring construya el singleton [ArticlesManagerWithDataBase], también tendrá que crear el singleton [ArticlesDaoPlainJdbc]:
- Spring establecerá un grafo de dependencias de los beans y verá que el bean [articlesManager] depende del bean [articlesDao]
- creará el bean [articlesDao], es decir, un objeto de tipo [ArticlesDaoPlainJdbc]
- luego creará el bean [articlesManager] de tipo [ArticlesManagerWithDataBase]
Imaginemos ahora una prueba JUnit para la clase [ArticlesManagerWithDataBase]. Podría verse así:
Veamos el proceso de creación de los dos singletons definidos en el archivo de Spring llamado [springArticlesManagerWithDataBase.xml].
- El método [setUp] anterior solicita una referencia del bean llamado [articlesManager]
- Spring consulta su archivo de configuración y encuentra el bean [articlesManager]. Si ya está creado, simplemente devuelve una referencia al objeto (singleton); de lo contrario, lo crea.
- Spring detecta la dependencia del bean [articlesManager] respecto al bean [articlesDao]. Por lo tanto, crea el singleton [articlesDao] de tipo [ArticlesDaoPlainJdbc] si este aún no existe (singleton).
- Crea el singleton [articlesManager] de tipo [ArticlesManagerWithDataBase]
Este mecanismo podría esquematizarse de la siguiente manera:
![]() |
Recordemos la estructura básica de la clase [ArticlesManagerWithDataBase]:
Al finalizar la construcción de los singletons por parte de Spring, tenemos un objeto de tipo [ArticlesManagerWithDataBase] cuyo campo [articlesDao] se ha inicializado sin que él sepa cómo. Se dice que se ha inyectado una dependencia en el objeto [ArticlesManagerWithDataBase]. También se dice que se ha invertido el control: ya no es el objeto [ArticlesManagerWithDataBase] el que toma la iniciativa de crear por sí mismo el objeto que implementa la interfaz [IArticlesDao] que necesita, sino que es la aplicación en el nivel más alto (al inicializarse) la que se encarga de crear todos los objetos que necesita, gestionando las dependencias entre ellos.
La principal ventaja de configurar el singleton [ArticlesManagerWithDataBase] mediante un archivo de Spring es que ahora se puede cambiar la clase de implementación correspondiente al campo [articlesDao] de la clase [ArticlesManagerWithDataBase] sin necesidad de modificar el código de esta última. Solo hay que cambiar el nombre de la clase en la definición del bean [articlesDao] en el archivo de Spring:
se convertirá, por ejemplo, en:
El bean [ArticlesManagerWithDataBase] funcionará con esta nueva clase de acceso a datos, sin siquiera darse cuenta.
2.3. Spring IoC en la práctica
2.3.1. Ejemplo 1
Consideremos la siguiente clase:
La clase presenta:
- dos campos privados: nombre y edad
- los métodos de lectura (get) y escritura (set) de estos dos campos
- un método toString para recuperar el valor del objeto [Personne] en forma de cadena de caracteres
- un método init que Spring llamará al crear el objeto, y un método close que se llamará al destruir el objeto
Para crear objetos de tipo [Personne], utilizaremos el siguiente archivo de Spring:
Este archivo se llamará config.xml.
- Define dos beans con las claves respectivas «persona1» y «persona2» de tipo [Personne]
- Inicializa los campos [nom, age] de cada persona
- define los métodos que se deben llamar durante la construcción inicial del objeto [init-method] y durante la destrucción del objeto [destroy-method]
Para nuestras pruebas, utilizaremos una única clase de prueba JUnit a la que iremos agregando métodos sucesivamente. La primera versión de esta clase será la siguiente:
Comentarios:
- Para obtener los beans definidos en el archivo [config.xml], utilizamos un objeto de tipo [ListableBeanFactory]. Existen otros tipos de objetos que permiten acceder a los beans. El objeto [ListableBeanFactory] se obtiene en el método [setUp] de la clase de prueba y se almacena en una variable privada. De esta manera, estará disponible para todos los métodos de prueba.
- El archivo [config.xml] se colocará en el [ClassPath] de la aplicación, c.a.d, en uno de los directorios que explora la máquina virtual de Java cuando busca una clase a la que hace referencia la aplicación. El objeto [ClassPathResource] sirve para buscar un recurso en el [ClassPath] de una aplicación, en este caso el archivo [config.xml].
- Spring puede utilizar archivos de configuración en diversos formatos. El objeto [XmlBeanFactory] permite analizar un archivo de configuración en formato XML.
- Al procesar un archivo de Spring se obtiene un objeto de tipo [ListableBeanFactory], en este caso el objeto bf. Con este objeto, se puede obtener un bean identificado por la clave C mediante bf.getBean(C).
- El método [test1] solicita y muestra el valor de los beans con las claves «persona1» y «persona2».
La estructura del proyecto Eclipse de nuestra aplicación es la siguiente:

Comentarios:
- La carpeta [src] contiene los códigos fuente. Los códigos compilados se guardarán en una carpeta [bin] que no se muestra aquí.
- El archivo [config.xml] se encuentra en la raíz de la carpeta [src]. Al compilar el proyecto, este se copia automáticamente a la carpeta [bin], que forma parte de la carpeta [ClassPath] de la aplicación. Es ahí donde lo busca el objeto [ClassPathResource].
- La carpeta [lib] contiene tres bibliotecas Java necesarias para la aplicación:
- commons-logging.jar y spring-core.jar para las clases de Spring
- junit.jar para las clases de JUnit
- la carpeta [lib] también forma parte del [ClassPath] de la aplicación
La ejecución del método [test1] de la prueba JUnit arroja los siguientes resultados:
Comentarios:
- Spring registra una serie de eventos mediante la biblioteca [commons-logging.jar]. Estos registros nos permiten comprender mejor el funcionamiento de Spring.
- El archivo [config.xml] se cargó y luego se procesó
- la operación*
forzó la creación del bean [personne1]. Se puede ver el registro de Spring al respecto. Debido a que en la definición del bean [personne1] habíamos escrito [init-method="init"], se ejecutó el método [init] del objeto [Personne] creado. Se muestra el mensaje correspondiente.
- La operación
ha mostrado el valor del objeto [Personne] creado.
- El mismo fenómeno se repite para el bean de clave [personne2].
- La última operación
personne2 = (Personne) bf.getBean("personne2");
System.out.println("personne2=" + personne2.toString());
no provocó la creación de un nuevo objeto de tipo [Personne]. Si hubiera sido así, se habría mostrado el método [init], lo cual no ocurre aquí. Este es el principio del singleton. Spring, por defecto, crea solo una instancia de los beans de su archivo de configuración. Es un servicio de referencias de objetos. Si se le solicita la referencia de un objeto que aún no se ha creado, lo crea y devuelve una referencia. Si el objeto ya se ha creado, Spring simplemente devuelve una referencia.
- Se puede observar que no hay rastro alguno del método [close] del objeto [Personne], a pesar de que lo habíamos escrito en la definición de los beans [destroy-method=close]. Es posible que este método solo se ejecute cuando el recolector de basura (garbage collector) recupere la memoria ocupada por el objeto. En el momento en que esto ocurre, la aplicación ya ha finalizado y la salida a pantalla no tiene ningún efecto. Por verificar.
Ahora que ya tenemos los fundamentos de una configuración de Spring, nuestras explicaciones serán un poco más rápidas.
2.3.2. Ejemplo 2
Consideremos la siguiente clase nueva [Voiture]:
La clase presenta:
- tres campos privados: tipo, marca y propietario. Estos campos pueden inicializarse y leerse mediante los métodos públicos get y set de los beans. También pueden inicializarse mediante el constructor Auto(String, String, Persona). La clase cuenta además con un constructor sin argumentos para cumplir con la norma JavaBean.
- un método toString para recuperar el valor del objeto [Voiture] en forma de cadena de caracteres
- un método init que Spring llamará inmediatamente después de la creación del objeto, y un método close que se llamará al destruir el objeto
Para crear objetos de tipo [Voiture], utilizaremos el siguiente archivo de Spring [config.xml]:
Este archivo agrega a las definiciones anteriores un bean con la clave «voiture1» de tipo [Voiture]. Para inicializar este bean, se podría haber escrito:
En lugar de optar por este método ya presentado, aquí hemos decidido utilizar el constructor Carro(String, String, Persona) de la clase. Por otra parte, el bean [voiture1] define el método que se debe llamar durante la construcción inicial del objeto [init-method] y el que se debe llamar durante la destrucción del objeto [destroy-method].
Para nuestras pruebas, utilizaremos la clase de prueba JUnit ya presentada, añadiéndole el siguiente método [test2]:
El método [test2] recupera el bean [voiture1] y lo muestra.
La estructura del proyecto de Eclipse sigue siendo la misma que en la prueba anterior. Al ejecutar el método [test2] de la prueba JUnit se obtienen los siguientes resultados:
Comentarios:
- el método [test2] solicita una referencia al bean [voiture1]
- línea 4: Spring inicia la creación del bean [voiture1], ya que este bean aún no se ha creado (singleton)
- línea 6: dado que el bean [voiture1] hace referencia al bean [personne2], este último bean se crea a su vez
- línea 7: se ha creado el bean [personne2]. A continuación, se ejecuta su método [init].
- línea 9: Spring indica que utilizará un constructor para crear el bean [voiture1]
- línea 10: se ha creado el bean [voiture1]. A continuación, se ejecuta su método [init].
- línea 11: el método [test2] muestra el valor del bean [voiture1]
2.3.3. Ejemplo 3
Introducimos la siguiente clase nueva [GroupePersonnes]:
Sus dos miembros privados son:
miembros: una matriz con las personas que forman parte del grupo
groupesDeTravail: un diccionario que asigna a una persona a un grupo de trabajo
Cabe señalar aquí que la clase [GroupePersonnes] no define un constructor sin argumentos para cumplir con la norma JavaBean. Recordemos que, en ausencia de cualquier constructor, existe un constructor «por defecto», que es el constructor sin argumentos y que no hace nada.
El objetivo aquí es mostrar cómo Spring permite inicializar objetos complejos, tales como aquellos que contienen campos de tipo matriz o diccionario. Agregamos un nuevo bean al archivo Spring [config.xml] anterior:
- La etiqueta <list> permite inicializar un campo de tipo matriz o que implemente la interfaz List con diferentes valores.
- La etiqueta <map> permite hacer lo mismo con un campo que implemente la interfaz Map
Para nuestras pruebas, utilizaremos la clase de prueba JUnit ya presentada, añadiéndole el siguiente método [test3]:
El método [test3] recupera el bean [groupe1] y lo muestra.
La estructura del proyecto de Eclipse sigue siendo la misma que en la prueba anterior. Al ejecutar el método [test3] de la prueba JUnit se obtienen los siguientes resultados:
Comentarios:
- el método [test3] solicita una referencia del bean [groupe1]
- línea 4: Spring inicia la creación de este bean
- dado que el bean [groupe1] hace referencia a los beans [personne1] y [personne2], estos dos beans se crean (líneas 6 y 9) y se ejecuta su método init (líneas 7 y 10)
- línea 11: se ha creado el bean [groupe1]. Ahora se ejecuta su método [init].
- línea 12: visualización solicitada por el método [test3].
2.4. Spring para configurar aplicaciones web de tres capas
2.4.1. Arquitectura general de la aplicación
Queremos construir una aplicación de tres capas con la siguiente estructura:
![]() |
- Las tres capas serán independientes gracias al uso de interfaces Java
- La integración de las tres capas se llevará a cabo mediante Spring
- Se crearán paquetes separados para cada una de las tres capas, que se llamarán Control, Domain y Dao. Un paquete adicional contendrá las aplicaciones de prueba.
La estructura de la aplicación en Eclipse podría ser la siguiente:

2.4.2. La capa DAO de acceso a datos
La capa DAO implementará la siguiente interfaz:
package istia.st.demo.dao;
public interface IDao1 {
public int doSometingInDaoLayer(int a, int b);
}
- Escriba dos clases, Dao1Impl1 y Dao1Impl2, que implementen la interfaz IDao1. El método Dao1Impl1. doSomethingInDaoLayer devolverá a+b y el método Dao1Impl2. doSomethingInDaoLayer devolverá a-b.
- escribir una clase de prueba JUnit que pruebe las dos clases anteriores
2.4.3. La capa de negocio
La capa de negocio implementará la siguiente interfaz:
package istia.st.demo.domain;
public interface IDomain1 {
public int doSomethingInDomainLayer(int a, int b);
}
- Escriba dos clases, Domain1Impl1 y Domain1Impl2, que implementen la interfaz IDomain1. Estas clases tendrán un constructor que reciba como parámetro un objeto de tipo IDao1. El método Domain1Impl1.doSomethingInDomainLayer incrementará a y b en una unidad y luego pasará estos dos parámetros al método doSomethingInDaoLayer del objeto de tipo IDao1 recibido. Por su parte, el método Domain1Impl2.doSomethingInDomainLayer disminuirá a y b en una unidad antes de hacer lo mismo.
- Escribir una clase de prueba JUnit que pruebe las dos clases anteriores
2.4.4. La capa de interfaz de usuario
La capa de interfaz de usuario implementará la siguiente interfaz:
package istia.st.demo.control;
public interface IControl1 {
public int doSometingInControlLayer(int a, int b);
}
- Escriba dos clases, Control1Impl1 y Control1Impl2, que implementen la interfaz IControl1. Estas clases tendrán un constructor que reciba un parámetro de tipo IDomain1. El método Control1Impl1.doSomethingInControlLayer incrementará a y b en una unidad y luego pasará estos dos parámetros al método doSomethingInDomainLayer del objeto de tipo IDomain1 recibido. El método Control11Impl2.doSomethingInControlLayer, por su parte, decrementará a y b en una unidad antes de hacer lo mismo.
- Escribir una clase de prueba JUnit que pruebe las dos clases anteriores
2.4.5. Integración con Spring
- Escribir un archivo de configuración de Spring que determinará qué clases deberá utilizar cada una de las tres capas anteriores
- Escribir una clase de prueba JUnit que utilice diferentes configuraciones de Spring, con el fin de resaltar la flexibilidad de la aplicación desarrollada
- Escribir una aplicación independiente (método main) que pase dos parámetros a la interfaz IControl1 y muestre el resultado generado por la interfaz.
2.4.6. Una solución
2.4.6.1. El proyecto Eclipse

Los archivos de la carpeta [lib] se han agregado a [ClassPath] del proyecto.
2.4.6.2. El paquete [istia.st.demo.dao]
La interfaz:
Una primera clase de implementación:
Una segunda clase de implementación:
2.4.6.3. El paquete [istia.st.demo.domain]
La interfaz:
Una primera clase de implementación:
Una segunda clase de implementación:
2.4.6.4. El paquete [istia.st.demo.control]
La interfaz
Una primera clase de implementación:
Una segunda clase de implementación:
2.4.6.5. Los archivos de configuración [Spring]
Un primer archivo [springMainTest1.xml]:
Un segundo [springMainTest2.xml]:
2.4.6.6. El paquete de pruebas [istia.st.demo.tests]
Una prueba de tipo [main]:
Los resultados obtenidos en la consola de Eclipse:
Otra prueba que utiliza el segundo archivo de configuración [Spring]:
Los resultados obtenidos en la consola de Eclipse:
Por último, una prueba con JUnit:
2.5. Conclusion
El marco Spring ofrece una gran flexibilidad tanto en la arquitectura de las aplicaciones como en su configuración. Hemos utilizado el concepto IoC, uno de los dos pilares de Spring. El otro pilar es AOP (programación orientada a aspectos), que no hemos presentado. Permite agregar, mediante configuración, «comportamiento» a un método de clase sin modificar el código de esta. Esquemáticamente, AOP permite filtrar las llamadas a ciertos métodos:
![]() |
- el filtro puede ejecutarse antes o después del método M de destino, o en ambos casos.
- El método M ignora la existencia de estos filtros. Estos se definen en el archivo de configuración de Spring.
- El código del método M no se modifica. Los filtros son clases de Java que deben crearse. Spring proporciona filtros predefinidos, en particular para gestionar las transacciones de SGBD.
- Los filtros son beans y, como tales, se definen en el archivo de configuración de Spring como beans.
Un filtro común es el filtro transaccional. Tomemos un método M de la capa de negocio que realiza dos operaciones inseparables sobre los datos (unidad de trabajo). Este método utiliza dos métodos, M1 y M2, de la capa DAO para llevar a cabo estas dos operaciones.
![]() |
Dado que se encuentra en la capa de negocio, el método M no tiene en cuenta el soporte de estos datos. Por ejemplo, no tiene que los datos se encuentren en un SGBD ni que deba incluir las dos llamadas a los métodos M1 y M2 dentro de una transacción de SGBD. Es la capa DAO la que debe encargarse de estos detalles. Una solución al problema anterior es, entonces, crear un método en la capa DAO que, a su vez, llame a los métodos M1 y M2, llamadas que incluiría en una transacción de SGBD.
![]() |
La solución de filtrado AOP es más flexible. Permitirá definir un filtro que, antes de llamar a M, iniciará una transacción y, después de la llamada, realizará un commit o un rollback, según corresponda.
![]() |
Este enfoque presenta varias ventajas:
- una vez definido el filtro, se puede aplicar a varios métodos, por ejemplo, a todos aquellos que requieran una transacción
- los métodos así filtrados no tienen que reescribirse
- los filtros que se utilizarán se definen mediante configuración, por lo que se pueden modificar
Además de los conceptos IoC y AOP, Spring ofrece numerosas clases de apoyo para aplicaciones de tres capas:
- para JDBC, SqlMap (iBATIS), Hibernate, JDO (Java Data Object) en la capa DAO
- para el modelo MVC en la capa de interfaz de usuario
Para más información: http://www.springframework.org.









