Buscar..


Observaciones

El código fuente para aplicaciones de software grandes se organiza típicamente en unidades múltiples. La definición de una unidad normalmente varía según el lenguaje de programación utilizado. Por ejemplo, el código escrito en un lenguaje de programación de procedimientos (como C) está organizado en functions o procedures . De manera similar, el código en un lenguaje de programación orientado a objetos (como Java, Scala y C #) se organiza en classes , interfaces , etc. Estas unidades de organización de código se pueden considerar como unidades individuales que constituyen la aplicación de software general.

Cuando las aplicaciones tienen varias unidades, las interdependencias entre esas unidades surgen cuando una unidad tiene que usar otras para completar su funcionalidad. Las unidades dependientes pueden considerarse como consumers y las unidades de las que dependen como providers de funcionalidad específica.

El enfoque de programación más sencillo es que los consumidores controlen completamente el flujo de una aplicación de software al decidir qué proveedores deben ser instanciados, utilizados y destruidos en qué puntos de la ejecución general de la aplicación. Se dice que los consumidores tienen control total sobre los proveedores durante el flujo de ejecución, que son dependencies para los consumidores. En caso de que los proveedores tengan sus propias dependencias, es posible que los consumidores tengan que preocuparse sobre cómo deben inicializarse (y liberarse) los proveedores, lo que hace que el flujo de control sea cada vez más complicado a medida que aumenta la cantidad de unidades en el software. Este enfoque también aumenta el acoplamiento entre unidades, lo que hace cada vez más difícil cambiar las unidades individualmente sin preocuparse por romper otras partes del software.

Inversion of Control (IoC) es un principio de diseño que aboga por la subcontratación de actividades de control de flujo como el descubrimiento, creación de instancias y destrucción de unidades en un marco independiente de los consumidores y proveedores. El principio subyacente detrás de IoC es desacoplar a los consumidores y proveedores, liberando a las unidades de software de tener que preocuparse por descubrir, crear instancias y limpiar sus dependencias y permitir que las unidades se centren en su propia funcionalidad. Este desacoplamiento ayuda a mantener el software extensible y mantenible.

La inyección de dependencia es una de las técnicas para implementar el principio de inversión de control mediante el cual las instancias de dependencias (proveedores) se inyectan en una unidad de software (el consumidor) en lugar de que el consumidor tenga que encontrarlas e instanciarlas.

El framework Spring contiene un módulo de inyección de dependencias en su núcleo que permite que los beans administrados por Spring se inyecten en otros beans administrados por Spring como dependencias.

Inyectar una dependencia manualmente a través de la configuración XML.

Considera las siguientes clases de Java:

class Foo {
  private Bar bar;

  public void foo() {
    bar.baz();
  }
}

Como puede verse, la clase Foo necesita llamar al método baz en una instancia de otra Bar clase para que su método foo funcione correctamente. Se dice que Bar es una dependencia para Foo ya que Foo no puede funcionar correctamente sin una instancia de Bar .

Inyección de constructor

Cuando se utiliza la configuración XML para el framework Spring para definir beans administrados por Spring, un bean de tipo Foo se puede configurar de la siguiente manera:

<bean class="Foo">
  <constructor-arg>
    <bean class="Bar" />
  </constructor-arg>
</bean>

o, alternativamente (más detallado):

<bean id="bar" class="bar" />

<bean class="Foo">
  <constructor-arg ref="bar" />
</bean>

En ambos casos, Spring Framework primero crea una instancia de Bar y la injects en una instancia de Foo . Este ejemplo asume que la clase Foo tiene un constructor que puede tomar una instancia de Bar como parámetro, es decir:

class Foo {
  private Bar bar;

  public Foo(Bar bar) { this.bar = bar; }
}

Este estilo se conoce como inyección de constructor porque la dependencia (instancia de Bar ) se inyecta a través del constructor de clase.

Inyección de propiedad

Otra opción para inyectar la dependencia de Bar en Foo es:

<bean class="Foo">
  <property name="bar">
    <bean class="Bar" />
  </property>
</bean>

o, alternativamente (más detallado):

<bean id="bar" class="bar" />

<bean class="Foo">
  <property name="bar" ref="bar" />
</bean>

Esto requiere que la clase Foo tenga un método de establecimiento que acepte una instancia de Bar , como:

class Foo {
  private Bar bar;

  public void setBar(Bar bar) { this.bar = bar; }
}

Inyectando una dependencia manualmente a través de la configuración de Java.

Los mismos ejemplos que se muestran arriba con la configuración XML se pueden volver a escribir con la configuración de Java de la siguiente manera.

Inyección de constructor

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo() { return new Foo(bar()); }
}

Inyección de propiedad

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo() {
    Foo foo = new Foo();
    foo.setBar(bar());

    return foo;
  }
}

Autowiring una dependencia a través de la configuración XML

Las dependencias se pueden conectar automáticamente cuando se utiliza la función de escaneo de componentes del framework Spring. Para que el cableado automático funcione, se debe realizar la siguiente configuración XML:

<context:annotation-config/>
<context:component-scan base-package="[base package]"/>

donde, base-package es el paquete Java completamente calificado dentro del cual Spring debe realizar la exploración de componentes.

Inyección de constructor

Las dependencias se pueden inyectar a través del constructor de la clase de la siguiente manera:

@Component
class Bar { ... }

@Component
class Foo {
  private Bar bar;

  @Autowired
  public Foo(Bar bar) { this.bar = bar; }
}

Aquí, @Autowired es una anotación específica de Spring. Spring también admite JSR-299 para habilitar la portabilidad de la aplicación a otros marcos de inyección de dependencias basados ​​en Java. Esto permite que @Autowired se reemplace con @Inject como:

@Component
class Foo {
  private Bar bar;

  @Inject
  public Foo(Bar bar) { this.bar = bar; }
}

Inyección de propiedad

Las dependencias también se pueden inyectar utilizando los métodos de establecimiento de la siguiente manera:

@Component
class Foo {
  private Bar bar;

  @Autowired
  public void setBar(Bar bar) { this.bar = bar; }
}

Inyección de campo

Autowiring también permite inicializar campos en instancias de clase directamente, de la siguiente manera:

@Component
class Foo {
  @Autowired
  private Bar bar;
}

Para las versiones 4.1+ de Spring puede usar Opcional para dependencias opcionales.

@Component
class Foo {

    @Autowired
    private Optional<Bar> bar;
}

El mismo enfoque se puede utilizar para el constructor DI.

@Component
class Foo {
    private Optional<Bar> bar;

    @Autowired
    Foo(Optional<Bar> bar) {
        this.bar = bar;
    }
}

Autowiring una dependencia a través de la configuración de Java

La inyección del constructor a través de la configuración de Java también puede utilizar el cableado automático, como:

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo(Bar bar) { return new Foo(bar); }
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow