Muestra las diferencias entre dos versiones de la página.
|
unidades:10_servidor:04_inyecciondependencias [2014/08/30 23:47] admin |
unidades:10_servidor:04_inyecciondependencias [2014/09/03 11:56] (actual) admin [La solución] |
||
|---|---|---|---|
| Línea 2: | Línea 2: | ||
| 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. | 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. | ||
| - | La DI intenta resolver el problema que hay en el código del ejemplo de JSON de hace 2 temas: | + | |
| + | ===== 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]> | <sxh java;highlight: [5]> | ||
| Línea 31: | Línea 33: | ||
| ¿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''. | ¿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. | + | 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> | ||
| + | |||