Spring IoC Container: Utilizando beans fuera del contenedor (y II)

logo spring

 Finalizamos este mini-howto con tres estrategias más y utilizando como base el mismo proyecto de ejemplo.

Estrategia 3 – Realizar inyecciones en atributos estáticos

Podemos definir un bean correspondiente a la clase externa al contenedor en la que queremos utilizar los beans de Spring, e inyectarle los beans que necesitemos en atributos estáticos por lo que estarán disponibles para todas las instancias del objeto aunque no hayan sido creadas por Spring.

Esta estrategia nos obliga a definir un bean cuya instancia nunca se utilizará lo que además implica que ese bean no se deba iniciar de forma lazy porque en ese caso nunca se instanciará y no se establecerán los beans en los atributos estáticos. No obstante, a diferencia de las estrategias anteriores, con esta posible solución no es necesario tener acceso al ServletContext.

package com.danielme.blog.springioc.obtenerbeans;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet en el que se recuperará el bean de Spring.
 * @author http://danielme.com
 *
 */
public class ServletPrueba extends HttpServlet 
{
	
	/**
	 * Identificador para serialización
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * Atributo estático que simula la inyección.
	 */
	private static  BeanSpring beanSpring;		

	/**
	 * Setter para el bean.
	 * @param beanSpring
	 */
	public void setBeanSpring(BeanSpring beanSpring) 
	{
		ServletPrueba.beanSpring = beanSpring;
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{				
		StringBuffer html = new StringBuffer();	    
	    html.append("<html><head><title>Spring IoC Container: Utilizando los beans fuera del contenedor - Proyecto de prueba </title></head><body><h3>");
	    html.append(beanSpring.getMensajeHelloWorld());
	    html.append("</h3></body></html>");

	    response.setContentType("text/html");
	    PrintWriter out = response.getWriter();
	    out.write(html.toString());
	    out.close();
	}

	
}

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

	<bean id="beanSpring" class="com.danielme.blog.springioc.obtenerbeans.BeanSpring"/>

	<bean id="servletPrueba" class="com.danielme.blog.springioc.obtenerbeans.ServletPrueba" lazy-init="false">
		<property name="beanSpring" ref="beanSpring"/>
	</bean>

</beans>

Estrategia 4 – Implementar la interfaz «ApplicationContextAware» de Spring

Esta estrategia puede proporcionar acceso desde cualquier clase a un recurso disponible en el contenedor de Spring gracias a una implementación de esta interfaz.Lo que haremos es recibir través del método setApplicationContext el contexto de Spring y guardarlo en un atributo estático. Asimismo, daremos acceso a ese atributo con el correspondiente getter.

package com.danielme.blog.springioc.obtenerbeans;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Ejemplo de implementación de ApplicationContextAware para acceder al contexto de Spring.
 * @author danielme.com
 *
 */
public class ApplicationContextHolder implements ApplicationContextAware  
{

	private static ApplicationContext applicationContext;
	
	/**
	 * Este método se ejecutará al ser instanciada la clase.
	 */
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
	{
		ApplicationContextHolder.applicationContext = applicationContext;		
	}
	
	public static ApplicationContext getApplicationContext()
	{
		return applicationContext;
	}


}

El bean en el applicationContext.xml:

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

	<bean id="beanSpring" class="com.danielme.blog.springioc.obtenerbeans.BeanSpring"/>

	<bean id="applicationContextHolder" class="com.danielme.blog.springioc.obtenerbeans.ApplicationContextHolder"/>
	
</beans>

Su uso en el servlet de prueba:

@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		BeanSpring beanSpring = (BeanSpring) ApplicationContextHolder.getApplicationContext().getBean("beanSpring");
		
	    StringBuffer html = new StringBuffer();	    
	    html.append("<html><head><title>Spring IoC Container: Utilizando los beans fuera del contenedor - Proyecto de prueba </title></head><body><h3>");
	    html.append(beanSpring.getMensajeHelloWorld());
	    html.append("</h3></body></html>");

	    response.setContentType("text/html");
	    PrintWriter out = response.getWriter();
	    out.write(html.toString());
	    out.close();
	}

Estrategia 5 – (Sólo para servlets) Implementar la interfaz HttpRequestHandler de Spring

En el caso de que tengamos que implementar un nuevo servlet y necesitemos acceder a los beans de Spring, existe una estrategia para poder usar directamente la inyección de dependencias sin recurrir a ninguno de los workarounds anteriores: implementar la interfaz HttpRequestHandler, equivalente en la práctica según la documentación, a HttpServlet, y hacer que el servlet sea gestionado por Spring como un bean más lo que permitirá inyectarle las dependencias que sean necesarias.

En primer lugar, adaptamos nuestro servlet implementando esa interfaz. El bean a inyectar lo definimos como un atributo y el cuerpo del método doGet ahora estará en el método handleRequest.

package com.danielme.blog.springioc.obtenerbeans;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.HttpRequestHandler;

/**
 * Servlet en el que se recuperará el bean de Spring, implementación de una interfaz de Spring y no
 * de javax.servlet.http.HttpServlet 
 * @author http://danielme.com
 *
 */
public class ServletPrueba  implements HttpRequestHandler 
{
	/**
	 * Atributo a inyectar
	 */
	private BeanSpring beanSpring;		

	public void setBeanSpring(BeanSpring beanSpring) 
	{
		this.beanSpring = beanSpring;
	}

	public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
	    StringBuffer html = new StringBuffer();	    
	    html.append("<html><head><title>Spring IoC Container: Utilizando los beans fuera del contenedor - Proyecto de prueba </title></head><body><h3>");
	    html.append(beanSpring.getMensajeHelloWorld());
	    html.append("</h3></body></html>");

	    response.setContentType("text/html");
	    PrintWriter out = response.getWriter();
	    out.write(html.toString());
	    out.close();
		
	}

	
}

Definimos el bean en Spring como cualquier otro bean, y le inyectamos lo que necesitemos:

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

	<bean id="beanSpring" class="com.danielme.blog.springioc.obtenerbeans.BeanSpring"/>

	<bean id="servletPrueba" class="com.danielme.blog.springioc.obtenerbeans.ServletPrueba">
		<property name="beanSpring" ref="beanSpring"/>
	</bean>

</beans>

La clave está en el web.xml, ahora el servlet hay que definirlo de la siguiente manera ( es imprescindible que el nombre del servlet coincida con el id de su bean de Spring):

    <servlet>
    	<servlet-name>servletPrueba</servlet-name>
    	<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
  </servlet>

Código de ejemplo

Descargar desde WordPress.comWordPress: debido a las limitaciones del servicio ofrecido por WordPress.com, el código de ejemplo está comprimido en formato zip pero con la extensión «.odt», por lo que hay que cambiar la extensión a «.zip» del fichero descargado o abrirlo directamente con el software adecuado.

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.