Inyección de Dependencias.
Este concepto Inyección de Dependencias tiene mucha popularidad en java últimamente gracias a Spring Framework. Es también parte fundamental de los módulos que componen Spring Framework Core Container y les explicare como funciona.
Definición
Es un proceso en el que los objetos definen su dependencias, esto se refiere a las instancias de los otros objetos con los que estos trabajan. Esto se puede lograr de las siguientes tres formas:
- Recibir la instancia como parámetro o argumento del constructor
- Tambien como parámetro o argumento hacia un metodo de fabrica.
- O como propiedad que es instanciada después que la clase sea construida.
El contenedor de Spring Framework inyecta estas dependencias cuando crea el Bean. Este proceso es inverso, lo cual lo liga al concepto Inversion de Control o mejor conocido como IoC,
El código es mucho mas limpio y desacoplado con el principio de Inyección de Dependencias. Es mucho mas efectivo cuando los objectos son entregados por sus dependencias.
Como vimos en el tutorial anterior (spring boot profiles parte 2) sin importar cual es el sistema operativo el código funciona de la misma manera. El objecto no tiene que buscar las dependencias o instancias de los objetos con los que trabaja ni su locación.
Puedes leer mas acerca de esto en la documentación oficial de Spring y puedes buscar un poco acerca de polimorfismo en Java.
https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html
https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-collaborators
Escenario de prueba
Hicimos una aplicación Stand Alone con Spring Boot que utiliza la terminal o unidad de commandos del sistema operativo, para ello necesita saber la sintaxis y algunas características de cada uno.
Tenemos una interface de un servicio que se llama sistema operativo, este servicio retornara unos valores únicos para cada sistema operativo, como lo es el nombre, la extension de librerías del OS y la extension de los archivos ejecutables.
Ejecucion
Este seria el resultado.
Inyección de dependencias
Por constructor
Este metodo es el mas recomendado, pues te daría la visibilidad necesaria de cuantas inyecciones tiene tu clase y es mas fácil de hacer debug.
@Controller public class DemoController { SistemaOperativoService sistemaOperativoService; @Autowired //Anotacion opcional desde version 4.3 public DemoController(SistemaOperativoService sistemaOperativoService) { this.sistemaOperativoService = sistemaOperativoService; } }
Metodo de fabrica o setter
Es mayormente utilizado para inyecciones opcionales.
@Controller public class DemoController { SistemaOperativoService sistemaOperativoService; public DemoController() { } @Autowired public void setSistemaOperativoService(SistemaOperativoService sistemaOperativoService) { this.sistemaOperativoService = sistemaOperativoService; } }
Directo en Propiedad
Muy rapido y efectivo con clases muy pequeñas.
@Controller public class DemoController { @Autowired SistemaOperativoService sistemaOperativoService; }
STOP: Nada de lo descrito anterior te sirve cuando tienes multiples implementaciones de una interface. hay que especificar el Bean deseado a inyectar.
Tambien hay 3 maneras de definirlo.
- @Primary: Puedes anotar una implementacion como “Primaria” para indicar que en caso de confusion inyecte este Bean:
-
@Service @Primary public class SistemaOperativoServiceWindows implements SistemaOperativoService{ //metodos de la interface }
-
- @Qualifier: Por medio de un String (iniciado con minúscula) indica explicitamente que Bean se debe de inyectar:
-
@Controller public class DemoController { SistemaOperativoService sistemaOperativoService; public DemoController(@Qualifier("sistemaOperativoServiceLinux")SistemaOperativoService sistemaOperativoService) { this.sistemaOperativoService = sistemaOperativoService } }
-
- Nombramiento: El nombre del parámetro que recibe el constructor debe tener el nombre del Bean que quieras inyectar. (OJO) Si hay una clase con anotación @Primary esta tendrá mayor peso e ignorara el nombramiento de la variable:
-
@Controller public class DemoController { SistemaOperativoService sistemaOperativoService; public DemoController(SistemaOperativoService sistemaOperativoServiceLinux) { this.sistemaOperativoService = sistemaOperativoServiceLinux; } }
-
BONUS
Mira mi video en youtube donde explico mas y puedes verme codificando estos ejemplos.
Gracias por llegar al final de este post, no olvides dejar tus comentarios.