César López de Felipe Abad

Consultor tecnológico de desarrollo de proyectos informáticos.

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/JEE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2011-08-22

Tutorial visitado 5.287 veces Descargar en PDF
Inyección de una lista de servicios en Spring.

Inyección de una lista de servicios en Spring.


0. Índice de contenidos.


1. Introducción.

En este tutorial vamos a ver como podemos inyectar una lista de servicios de Spring mediante un archivo xml o mediante anotaciones. Esto puede resultarnos útil si queremos crear una interfaz o una clase abstracta que implementen o extiendan nuestros servicios y luego utilizar la lista sin necesidad de saber que tipo de clase estamos usando.

En este sencillo ejemplo crearemos tres tareas para tres departamentos de una empresa, que implementarán la interfaz TaskProvider con un método para que nos devuelvan el nombre de la tarea. En el ejemplo simplemente devolverán un String con el nombre de la tarea, pero podríamos querer que cada implementación realizase las consultas o procesos necesarios para generar su tipo de tarea, para lo que si necesitaríamos otros beans de Spring como podría ser por ejemplo un Dao.

Para probar que se realiza la inyección correctamente mediante el xml y mediante anotaciones haremos dos test.


2. Entorno.

  • Hardware: MacBookPro8,2 (2 GHz Intel Core i7, 4GB DDR3 SDRAM).
  • AMD Radeon HD 6490M 256MB.
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.7.
  • Eclipse Helios
  • Maven 3.0.3
  • Spring 3.0.5.RELEASE

3. Creación del proyecto y las clases de las tareas.

Creamos un proyecto de maven y le añadimos las dependencias de spring y junit al pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.autentia.tutoriales</groupId>
	<artifactId>springinjection</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>


		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>


		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>3.0.5.RELEASE</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.6</version>
			<scope>test</scope>
		</dependency>
		
	</dependencies>
</project>

Después nos creamos nuestra interfaz TaskProvider:

package com.autentia.tutoriales.springinjection;

public interface TaskProvider {

	public String getName();

}

Y las tres clases que la implementarán:

package com.autentia.tutoriales.springinjection;

public class TaskProviderForSales implements TaskProvider {

	public String getName() {
		return "This is a task for sales department";
	}
}

package com.autentia.tutoriales.springinjection;

public class TaskProviderForManagement implements TaskProvider {

	public String getName() {
		return "This is a task for management department";
	}

}

package com.autentia.tutoriales.springinjection;

public class TaskProviderForHumanResources implements TaskProvider {

	public String getName() {
		return "This is a task for human resources department";
	}

}

4. Realizar la inyección con un archivo xml.

Ahora creamos nuestro archivo xml para configurar la lista de TaskProviders, yo lo he llamado applicationContext-xml-injection-test.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="taskProviderForManagement" class="com.autentia.tutoriales.springinjection.TaskProviderForManagement" />

	<bean id="taskProviderForHumanResources" class="com.autentia.tutoriales.springinjection.TaskProviderForHumanResources" />

	<bean id="taskProviderForSales" class="com.autentia.tutoriales.springinjection.TaskProviderForSales" />

	<util:list id="tasksList" list-class="java.util.ArrayList" value-type="com.autentia.tutoriales.springinjection.TaskProvider">
		<ref bean="taskProviderForManagement"/>
		<ref bean="taskProviderForHumanResources"/>
		<ref bean="taskProviderForSales"/>
	</util:list>

</beans>  

Y ahora creamos nuestra clase de test para probar que funciona:

package com.autentia.tutoriales.springinjection;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.List;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-xml-injection-test.xml" })
public class TaskProviderXmlInjection {
	
	@Resource 
	ApplicationContext applicationContext;
	
	@Test
	public void shouldLoad3TaskProviders() {
		@SuppressWarnings("unchecked")
		final List<TaskProvider> taskProviders = (List<TaskProvider>) applicationContext.getBean("tasksList");
	
		assertEquals(3,taskProviders.size());		
	}
	
	@Test
	public void shouldLoadThe3DifferentProviders() {
		@SuppressWarnings("unchecked")
		final List<TaskProvider> taskProviders = (List<TaskProvider>) applicationContext.getBean("tasksList");
		
		boolean containsHumanResources = false;
		boolean containsSales = false;
		boolean containsManagement = false;

		for (TaskProvider taskProvider : taskProviders) {
			if (taskProvider.getClass().equals(
					TaskProviderForHumanResources.class)) {
				containsHumanResources = true;
			}
			if (taskProvider.getClass().equals(TaskProviderForSales.class)) {
				containsSales = true;
			}
			if (taskProvider.getClass().equals(TaskProviderForManagement.class)) {
				containsManagement = true;
			}
		}

		assertTrue(containsHumanResources);
		assertTrue(containsSales);
		assertTrue(containsManagement);
	}
	
}

5. Realizar la inyección con anotaciones.

Vamos a hacer lo mismo utilizando anotaciones, anotamos las tres implementaciones con @Service y creamos otro archivo xml (applicationContext-annotation-test.xml):

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:annotation-config />
	
	<context:component-scan base-package="com.autentia.tutoriales.springinjection" />
	
</beans>  

En el que decimos que usamos anotaciones y el paquete donde tiene que buscar los componentes anotados (que es en el qué estarán nuestros servicios).

Y el test para probar que funciona:

package com.autentia.tutoriales.springinjection;

import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;

import java.util.List;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.autentia.tutoriales.springinjection.TaskProvider;
import com.autentia.tutoriales.springinjection.TaskProviderForHumanResources;
import com.autentia.tutoriales.springinjection.TaskProviderForManagement;
import com.autentia.tutoriales.springinjection.TaskProviderForSales;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-annotation-test.xml" })
public class TaskProviderAnnotationInjectionTest {

	@Resource
	private List<TaskProvider> taskProviders;

	@Test
	public void shouldLoad3TaskProviders() {
		assertEquals(3, taskProviders.size());
	}

	@Test
	public void shouldLoadThe3DifferentProviders() {
		boolean containsHumanResources = false;
		boolean containsSales = false;
		boolean containsManagement = false;

		for (TaskProvider taskProvider : taskProviders) {
			if (taskProvider.getClass().equals(
					TaskProviderForHumanResources.class)) {
				containsHumanResources = true;
			}
			if (taskProvider.getClass().equals(TaskProviderForSales.class)) {
				containsSales = true;
			}
			if (taskProvider.getClass().equals(TaskProviderForManagement.class)) {
				containsManagement = true;
			}
		}

		assertTrue(containsHumanResources);
		assertTrue(containsSales);
		assertTrue(containsManagement);
	}

}

6. Conclusiones.

Hemos podido ver como podemos inyectar fácilmente una lista de servicios desde un archivo xml o mediante anotaciones. Si quereís descargaros los fuentes podéis hacerlo aquí.

Espero que os haya resultado útil.

Un saludo.

César López.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL: