Spring @Autowired es una de las anotaciones más habituales cuando trabajamos con Spring Framework ya que se trata de la anotación que permite inyectar unas dependencias con otras dentro de Spring .
Spring @Autowired y su funcionamiento
Normalmente estamos acostumbrados a usar @AutoWired a nivel de la propiedad que deseamos inyectar. Spring funciona como una mega factoria de objetos. Cada clase se registra para instanciar objetos con alguna de las anotaciones @Controller ,@Service ,@repository o @RestController.
Una vez que los objetos estan creados la anotación Spring @Autowired se encarga de construir las ligazones entre los distintos elementos
Por ejemplo este caso es habitual cuando tenemos un servicio y un repositorio. Vamos a verlo usando Spring Boot
package com.arquitecturajava.wired; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; @Repository public class LibroRepository { public List<Libro> buscarTodos() { List<Libro> lista= new ArrayList<Libro>(); lista.add(new Libro ("1","java","pedro")); lista.add(new Libro ("2","python","gema")); return lista; } }
Como podemos ver tenemos el LibroRepository como primer componente y le queremos enlazar desde un Servicio.
package com.arquitecturajava.wired; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class LibroRestService { @Autowired LibroRepository repositorio; @RequestMapping("/libros") public List<Libro> buscarTodos() { return repositorio.buscarTodos(); } }
Ahora tenemos los dos elementos enlazados y un ServicioREST publicado por lo tanto si ejecutamos la aplicación de Spring Boot dispondremos de una Url con un listado de Libros disponible
Spring Testing y Wiring
Hoy por hoy las metodologías de TDD cada día se usan más y aunque este uso de la anotacion @Autowired es el más habitual suele ser más práctico y cómodo para el manejo de test realizar un @Autowired a nivel de constructores por lo tanto el código quedaría así:
package com.arquitecturajava.wired; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class LibroRestService { LibroRepository repositorio; @Autowired public LibroRestService(LibroRepository repositorio) { this.repositorio=repositorio; } @RequestMapping("/libros") public List<Libro> buscarTodos() { return repositorio.buscarTodos(); } }
De esta manera el código queda más limpio , flexible y más sencillo de usar cuando utilicemos Test Driven Development.
[…] Inyección de Dependencias:https://www.arquitecturajava.com/spring-autowired-y-la-inyeccion-de-dependencias/ […]
Gracias por compartir Cecilio, dos comentarios, cuando se inyecta vía constructor la anotación autowired normalmente no es necesaria (esto es así desde la versión 4.3 de spring) y la manera recomendada de inyectar por la documentación oficial es de hecho la de constructor https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-constructor-injection (ver sección resaltada que las compara). Inyectar por field debe hacerse pocas veces. Dejo acá una referencia de Oliver Drotbohm (uno de los commiters de spring) http://olivergierke.de/2013/11/why-field-injection-is-evil/.
Gracias por el aporte 🙂
gracias por el aporte
Qué tal Juan, Cecilio, me intrigó tu comentario Juan, entonces ¿ se ocupa o no @Autowired siguiendo la práctica de inyectar por constructor? porque si no es necesaria la anotación cuando es por constructor y lo recomendable es hacerlo por constructor ¿se debe usar o no? creo que ahora me confundí más, revisaré las referencias que dejas a ver si comprendo mejor y si hay algo que quieran comentar les agradecería, saludos, gracias por compartir.
En principio a partir de la version 4.3 no haría falta usarlo , inyectaríamos por constructor
Para esta manera, es mucho mas efectivo a nivel de memoria y todo hacer simplemente un singleton sin usar un autowired.
Normalmente cuando uno usa spring todo se inyecta
¿Puedes dar un ejemplo de por qué sería más sencillo testear con constructor?
Yo para testing unitario utilizo jmockit y me parece bastante simple el testeo con autowireds por ejemplo.
Sera más sencillo saber las dependencias de la clase , no que en sí sea más sencillo de testear pero si de ganar vision sobre las dependencias