Introducción a inversión de control e inyección de dependencias con Spring

Introducción a inversión de control e inyección de dependencias con Spring


visión general

en este artículo, presentaremos los conceptos de IOC (inversión de Control) e DI (inyección de dependencias), y luego echaremos un vistazo a cómo se implementan en el framework Spring.,

más información:

Wiring in Spring: @Autowired, @ Resource and @Inject

este artículo comparará y contrastará el uso de anotaciones relacionadas con la inyección de dependencias, a saber, las anotaciones @Resource, @Inject y @Autowired.
Leer más →

@Component vs @Repository y @Service en primavera

conozca las diferencias entre las anotaciones @Component, @Repository y @Service y cuándo usarlas.
Leer más →

¿Qué Es la Inversión de Control?,

la inversión de Control Es un principio en la ingeniería de software por el cual el control de objetos o porciones de un programa se transfiere a un contenedor o marco. Se utiliza con mayor frecuencia en el contexto de la programación orientada a objetos.

a diferencia de la programación tradicional, en la que nuestro código personalizado hace llamadas a una biblioteca, IoC permite a un framework tomar el control del flujo de un programa y hacer llamadas a nuestro código personalizado. Para habilitar esto, los frameworks usan abstracciones con comportamiento adicional incorporado., Si queremos añadir nuestro propio comportamiento, necesitamos extender las clases del framework o plugin nuestras propias clases.,

Las ventajas de esta arquitectura son:

  • desacoplar la ejecución de una tarea de su implementación
  • haciendo más fácil cambiar entre diferentes implementaciones
  • mayor modularidad de un programa
  • mayor facilidad en probar un programa aislando un componente o burlándose de sus dependencias y permitiendo que los componentes se comuniquen a través de contratos

la inversión de Control se puede lograr a través de diversos mecanismos como:, patrón de fábrica e inyección de dependencia (di).,

vamos a ver DI siguiente.

¿Qué es la inyección de dependencia?

La inyección de dependencias es un patrón a través del cual implementar IoC, donde el control que se invierte es el ajuste de las dependencias del objeto.

el acto de conectar objetos con otros objetos, o» inyectar » objetos en otros objetos, es realizado por un ensamblador en lugar de por los propios objetos.,

así es como crearías una dependencia de objeto en la programación tradicional:

public class Store { private Item item; public Store() { item = new ItemImpl1(); }}

en el ejemplo anterior, necesitamos crear una instancia de una implementación de la interfaz de elemento dentro de la propia clase Store.

Usando DI, podemos reescribir el ejemplo sin especificar la implementación del elemento que queremos:

public class Store { private Item item; public Store(Item item) { this.item = item; }}

en las siguientes secciones, veremos cómo podemos proporcionar la implementación del elemento a través de metadatos.,

tanto el coi como el DI son conceptos simples, pero tienen profundas implicaciones en la forma en que estructuramos nuestros sistemas, por lo que vale la pena entenderlos bien.

El contenedor IoC de resorte

un contenedor IoC es una característica común de los frameworks que implementan IoC.

en el framework Spring, el contenedor IoC está representado por la interfaz ApplicationContext. El contenedor Spring es responsable de crear instancias, configurar y ensamblar objetos conocidos como beans, así como de administrar su ciclo de vida.,

el framework Spring proporciona varias implementaciones de la interfaz ApplicationContext: ClassPathXmlApplicationContext y FileSystemXmlApplicationContext para aplicaciones independientes, y WebApplicationContext para aplicaciones web.

para ensamblar beans, el contenedor utiliza metadatos de configuración, que pueden ser en forma de configuración XML o anotaciones.

Aquí hay una forma de crear una instancia manual de un contenedor:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

para establecer el atributo item en el ejemplo anterior, podemos usar metadatos., Luego, el contenedor leerá estos metadatos y los usará para ensamblar beans en tiempo de ejecución.

La inyección de dependencias en primavera se puede hacer a través de Constructores, configuradores o campos.

inyección de dependencias basada en Constructores

en el caso de inyección de dependencias basada en Constructores, el contenedor invocará a un constructor con argumentos cada uno representando una dependencia que queremos establecer.

Spring resuelve cada argumento principalmente por tipo, seguido por el nombre del atributo y el índice para la desambiguación., Veamos la configuración de un bean y sus dependencias usando anotaciones:

la anotación @Configuration indica que la clase es una fuente de definiciones de bean. Además, podemos añadirlo a múltiples clases de configuración.

la anotación @Bean se usa en un método para definir un bean. Si no especificamos un nombre personalizado, el nombre de bean será por defecto el nombre del método.

para un bean con el ámbito singleton predeterminado, Spring primero comprueba si una instancia en caché del bean ya existe y solo crea una nueva si no lo hace., Si estamos utilizando el ámbito prototipo, el contenedor devuelve una nueva instancia de bean para cada llamada a método.

otra forma de crear la configuración de los beans es a través de la configuración XML:

inyección de dependencias basada en Setter

para el DI basado en setter, el contenedor llamará a los métodos setter de nuestra clase, después de invocar un constructor sin argumento o un método de fábrica estático sin argumento para instanciar el bean., Vamos a crear esta configuración usando anotaciones:

@Beanpublic Store store() { Store store = new Store(); store.setItem(item1()); return store;}

También podemos usar XML para la misma configuración de beans:

<bean class="org.baeldung.store.Store"> <property name="item" ref="item1" /></bean>

los tipos de inyección basados en Constructor y setter se pueden combinar para el mismo bean. La documentación de Spring recomienda usar la inyección basada en constructor para las dependencias obligatorias, y la inyección basada en setter para las opcionales.

7., Inyección de dependencias basada en campo

en el caso de DI basada en campo, podemos inyectar las dependencias marcándolas con una anotación @Autowired:

public class Store { @Autowired private Item item; }

mientras construimos el objeto Store, si no hay un método constructor o setter para inyectar el item bean, el contenedor usará reflexión para inyectar el Item En Store.

también podemos lograr esto usando la configuración XML.,

este enfoque puede parecer más simple y limpio, pero no se recomienda su uso porque tiene algunos inconvenientes como:

  • este método utiliza la reflexión para inyectar las dependencias, lo que es más costoso que la inyección basada en Constructores o en configuradores
  • Es realmente fácil seguir agregando varias dependencias utilizando este enfoque. Si estuviera usando inyección de constructor tener múltiples argumentos nos habría hecho pensar que la clase hace más de una cosa que puede violar el principio de responsabilidad única.,

Se puede encontrar más información sobre la anotación @Autowired en el artículo Wiring In Spring.

dependencias de Autowiring

Wiring permite que el contenedor Spring resuelva automáticamente las dependencias entre los frijoles colaboradores inspeccionando los frijoles que se han definido.,

Hay cuatro modos de autowiring de un bean usando una configuración XML:

  • no: el valor predeterminado – esto significa que no se usa autowiring para el bean y tenemos que nombrar explícitamente las dependencias
  • byName: el autowiring se hace basado en el nombre de la propiedad, por lo tanto Spring buscará un bean con el mismo nombre que la propiedad que necesita ser establecida
  • byType: similar al byname autowiring, solo basado en tipo de propiedad. Esto significa que Spring buscará un frijol con el mismo tipo de propiedad para establecer., Si hay más de un bean de ese tipo, el framework lanza una excepción.,también puede inyectar frijoles usando la anotación @Autowired para el auto cableado por tipo:

    public class Store { @Autowired private Item item;}

    Si hay más de un frijol del mismo tipo, podemos usar la anotación @Qualifier para hacer referencia a un frijol por nombre:

    public class Store { @Autowired @Qualifier("item1") private Item item;}

    Ahora, vamos a autowire frijoles por tipo a través de la configuración XML:

    <bean class="org.baeldung.store.Store" autowire="byType"> </bean>

    a continuación, vamos a inyectar un elemento con nombre bean en la propiedad Item de Store Bean by name a través de XML:

    <bean class="org.baeldung.store.ItemImpl1" /><bean class="org.baeldung.store.Store" autowire="byName"></bean>

    También podemos anular el autowiring definiendo dependencias explícitamente a través de argumentos de constructor o setters.,

    frijoles inicializados perezosos

    de forma predeterminada, el contenedor crea y configura todos los frijoles singleton durante la inicialización. Para evitar esto, puede usar el atributo lazy-init con valor true en la configuración de bean:

    <bean class="org.baeldung.store.ItemImpl1" lazy-init="true" />

    como consecuencia, el bean item1 se inicializará solo cuando se solicite por primera vez, y no al inicio., La ventaja de esto es un tiempo de inicialización más rápido, pero la compensación es que los errores de configuración pueden descubrirse solo después de que se solicite el bean, lo que podría ser varias horas o incluso días después de que la aplicación ya se haya estado ejecutando.

    Conclusión

    En este artículo, hemos presentado los conceptos de inversión de control e inyección de dependencias y ejemplificado en el framework Spring.

    Puede Leer más sobre estos conceptos en los artículos de Martin Fowler:

    • inversión de contenedores de Control y el patrón de inyección de dependencias.,
    • inversión de Control

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *