Herramientas de usuario

Herramientas del sitio


unidades:10_servidor:04_inyecciondependencias

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Próxima revisión
Revisión previa
unidades:10_servidor:04_inyecciondependencias [2014/08/30 23:18] – creado adminunidades:10_servidor:04_inyecciondependencias [2014/09/03 11:56] (actual) – [La solución] admin
Línea 1: Línea 1:
 ====== 10.4 Inyección de dependencias ====== ====== 10.4 Inyección de dependencias ======
 +La inyección de dependencias (en inglés Dependency Injection, DI) es un patrón de diseño sencillo de usar aunque quizás resulte algo muy novedoso para algunas personas. 
 +
 +
 +===== El problema =====
 +La inyección de dependencias intenta resolver el problema que hay en el código del ejemplo de JSON de hace 2 temas:
 +
 +<sxh java;highlight: [5]>
 +public class Main {
 + 
 + 
 +    public static void main(String[] args) {
 +        JsonTransformer jsonTransformer=new JsonTransformerImplJackson();
 +         
 +        Usuario usuario=new Usuario("Alberto Tortosa","alberto_tortosa@gmail.com",91);
 +         
 +        String jsonUsuario=jsonTransformer.toJson(usuario);
 +         
 +        System.out.println(jsonUsuario);
 +         
 +         
 +        Usuario newUsuario=(Usuario) jsonTransformer.fromJson(jsonUsuario, Usuario.class);
 +           
 +        System.out.println("Nombre:"+newUsuario.getNombre());
 +        System.out.println("E-Mail:"+newUsuario.getEmail());
 +        System.out.println("Edad:"+newUsuario.getEdad());
 +         
 +    }
 +     
 +}
 +</sxh>
 +
 +¿Cual es el problema que hay en ese código? ¡Si lo hicimos muy bien añadiendo el interfaz para abstraernos de saber nada de Jackson! Pero , ¿Seguro que no sabemos nada de Jackson? Si te fijas en la línea 5 verás que aparece la palabra "Jackson" en la clase ''JsonTransformerImplJackson''. 
 +
 +El problema es que tenemos dentro del código la implementación que usamos del interfaz y si usamos el interfaz para no saber nada sobre su implementación es un sin sentido que tengamos en el propio código una referencia a la implementación. Además is quisiéramos cambiar la implementación deberíamos ir por todo el código buscando donde se usa para cambiarlo.
 +
 +===== La solución =====
 +La solución a todo ésto es la **Inyección de Dependencias** que evita que nuestro código tenga referencias a las implementaciones que usamos.
 +
 +Vamos a modificar el controlador ''UsuarioController '' del tema anterior de forma que usemos ''JsonTransformer'':
 +
 +<sxh java;highlight: [6];title:UsuarioController.java>
 +@Controller
 +public class UsuarioController {
 +
 +    @RequestMapping(value = {"/Usuario"})
 +    public void prueba(HttpServletRequest httpRequest, HttpServletResponse httpServletResponse) throws IOException {
 +        JsonTransformer jsonTransformer=new JsonTransformerImplJackson();
 +        
 +        Usuario usuario=new Usuario("Alberto Tortosa","alberto_tortosa@gmail.com",91);
 +        String jsonUsuario=jsonTransformer.toJson(usuario);
 +        
 +        httpServletResponse.getWriter().println(jsonUsuario);
 +    }
 +}
 +</sxh>
 +Vemos que ahora el controlador en vez de mostrar en la página web el texto "Hola mundo" retornara el JSON:
 +  {"nombre":"Alberto Tortosa","email":"alberto_tortosa@gmail.com","edad":91}
 +
 +Pero seguimos teniendo el mismo problema que antes. ¿Como lo resolvemos? Como ya tenemos configurado Spring en esta aplicación , nos va a resultar muy sencillo. Simplemente vamos a hacer unas pequeñas modificaciones:
 +  * Decirle a Spring cual es la clase con la implementación de ''JsonTransformer''
 +  * Quitar la referencia a la implementación del controlador
 +  * Indicar a Spring que inyecte la implementación en el controlador.
 +
 +Vamos a modificar el fichero ''applicationContext.xml''
 +<sxh xml;highlight: [12];title: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"
 +       xmlns:context="http://www.springframework.org/schema/context"
 +       xsi:schemaLocation="
 +       http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 +       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
 +">
 + 
 +    <context:annotation-config/>
 + 
 +    <bean class="es.cursoangularjs.inyecciondependencias.json.JsonTransformerImplJackson" />
 +    
 +</beans>
 +</sxh>
 +  * Línea 12: Hemos añadido la clase ''es.cursoangularjs.inyecciondependencias.json.JsonTransformerImplJackson'' diciendo que ahora puede ser inyectada si solicitan una implementación del interfaz ''JsonTransformer''
 +  
 +¿Como sabe Spring que esa clase se debe inyectar si solicitan el interfaz ''JsonTransformer''? Muy sencillo porque mira la clase y ve que implementa ese interfaz.
 +
 +Ahora debemos modificar el controlador para que le inyecten la clase definida en el fichero ''applicationContext.xml''.
 +
 +<sxh java;title:UsuaroiController.java;highlight: [4,5]>
 +@Controller
 +public class UsuarioController {
 +    
 +    @Autowired
 +    private JsonTransformer jsonTransformer;
 +    
 +    @RequestMapping(value = {"/Usuario"})
 +    public void prueba(HttpServletRequest httpRequest, HttpServletResponse httpServletResponse) throws IOException {
 +        Usuario usuario=new Usuario("Alberto Tortosa","alberto_tortosa@gmail.com",91);
 +        String jsonUsuario=jsonTransformer.toJson(usuario);
 +        
 +        httpServletResponse.getWriter().println(jsonUsuario);
 +    }
 +}
 +</sxh>
 +  * Línea 5: Esta línea le dice a Spring que debe buscar una implementación del interfaz que hay a continuación y asignarle una instancia a la propiedad.
 +  * Línea 6: Declaramos ahora la propiedad privada ''jsonTransformer'' pero no indicamos el objeto que lo implementa. Eso lo inyectará automáticamente Spring
 +
 +Es decir que ahora la configuración sobre de implementaciones debemos usar está centralizada en el fichero ''applicationContext.xml'' y el resto de la aplicación gracias a la anotación ''@Autowired'' permite que se le inyecte la implementación que está definida en el fichero. Es decir que inyectar significa simplemente asignar un objeto a una propiedad pero sin que la clase a la que se le inyecta el objeto sepa de que clase es.
 +
 +<note important>
 +Una cosa importante a tener en cuenta es que spring solo va a crear un única instancia de objeto a inyectar en toda la aplicación por lo que hay que tener cuidado con mantener un estado en el objeto o controlar el acceso de varias threads a la vez.
 +</note>
 +===== Ejemplo =====
 +El ejemplo de esta unidad es exactamente lo que acabamos de contar pero es un nuevo proyecto llamado "inyecciondependencias".
 +Lo único que debes recordar es que se han añadido también las librerías de Jackson y Spring.
 +
 +<note>
 +Este ejemplo se encuentra en  git en [[https://github.com/logongas/cursoangularjs/tree/master/inyecciondependencias]]
 +</note>
 +
  
unidades/10_servidor/04_inyecciondependencias.1409433503.txt.gz · Última modificación: por admin