Inyección de una lista de servicios en Spring

0
13238

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.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad