¿Qué es la inyección de dependencia y la inversión de control en Spring Framework?


111

La "inyección de dependencia" y la "inversión de control" se mencionan a menudo como las principales ventajas de usar el marco Spring para desarrollar marcos web.

¿Alguien podría explicar qué es en términos muy simples con un ejemplo si es posible?



3
@SteveChambers no está duplicado, esta pregunta se hace en Springs Perspective. Esa pregunta es, en general, prospectiva.
VdeX

Respuestas:


233
  • Spring ayuda en la creación de aplicaciones poco acopladas debido a la inyección de dependencia .
  • En Spring, los objetos definen sus asociaciones (dependencias) y no se preocupan por cómo obtendrán esas dependencias . Es responsabilidad de Spring proporcionar las dependencias necesarias para crear objetos.

Por ejemplo : supongamos que tenemos un objeto Employeey tiene una dependencia del objeto Address. Definiríamos un bean correspondiente al Employeeque definirá su dependencia del objeto Address.

Cuando Spring intente crear un Employeeobjeto, verá que Employeetiene una dependencia de Address, por lo que primero creará el Addressobjeto (objeto dependiente) y luego lo inyectará en el Employeeobjeto.

  • La inversión de control ( IoC ) y la inyección de dependencia ( DI ) se utilizan indistintamente. IoC se logra a través de DI. DI es el proceso de proporcionar las dependencias e IoC es el resultado final de DI. ( Nota: DI no es la única forma de lograr IoC. También hay otras formas ).

  • Por DI, la responsabilidad de crear objetos se traslada del código de nuestra aplicación al contenedor Spring; este fenómeno se llama IoC.

  • La inyección de dependencia se puede realizar mediante inyección de setter o inyección de constructor.

Estoy en desacuerdo. No creo que esta sea una explicación clara. ¿Por qué no puede simplemente crear una instancia de "Dirección" dentro de "Empleado" en lugar de obtener un marco para crearlo e inyectarlo? Se requiere un ejemplo un poco más detallado.
Boris

2
@Boris Nadie dijo que no se pueden crear instancias de sus propios objetos. Pero el único propósito de la respuesta fue demostrar cómo puede lograr lo mismo con DI. Puede hacer que tanto DI como objetos instanciados por código de cliente. Esto todavía se llamaría COI, al menos parcialmente.
bogdan.rusu


Boris. ¿Muy celoso? Esa es la mejor respuesta de todas.
Aniket Kapse

31

Escribiré mi comprensión simple de estos dos términos: (Para una comprensión rápida, solo lea ejemplos)

  • Inyección de dependencia (DI): la
    inyección de dependencia generalmente significa pasar un objeto dependiente como parámetro a un método, en lugar de que el método cree el objeto dependiente .
    Lo que significa en la práctica es que el método no tiene una dependencia directa de una implementación particular; cualquier implementación que cumpla con los requisitos se puede pasar como parámetro.

    Con esta implementación de objetos se definen sus dependencias. Y la primavera lo hace disponible.
    Esto conduce a un desarrollo de aplicaciones poco acoplado.

    Ejemplo rápido: OBJETO DE EMPLEADO CUANDO SE CREA, AUTOMÁTICAMENTE CREARÁ OBJETO DE DIRECCIÓN (si la dirección se define como dependencia por el objeto de Empleado) *.

  • Contenedor de inversión de control (IoC):
    esta es una característica común de los marcos, IoC administra objetos java
    , desde la creación de instancias hasta la destrucción a través de su BeanFactory.
    - Los componentes de Java instanciados por el contenedor de IoC se denominan beans, y el contenedor de IoC administra el alcance de un bean, los eventos del ciclo de vida y cualquier característica de AOP para la que se haya configurado y codificado.

    QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

    Al implementar Inversión de control, un consumidor de software / objetos obtiene más controles / opciones sobre el software / objetos, en lugar de ser controlado o tener menos opciones.

    La inversión del control como directriz de diseño tiene los siguientes propósitos:
    - Existe un desacoplamiento entre la ejecución de una determinada tarea y la implementación.
    - Cada módulo puede enfocarse en lo que está diseñado.
    - Los módulos no hacen suposiciones sobre lo que hacen otros sistemas, sino que dependen de sus contratos.
    - Reemplazar módulos no tiene efectos secundarios en otros módulos

Mantendré las cosas abstractas aquí, puede visitar los siguientes enlaces para una comprensión detallada del tema.

Una buena lectura con ejemplo

Explicación detallada


11

En Spring, los objetos están débilmente acoplados, es decir, cada clase es independiente entre sí para que todo pueda probarse individualmente. Pero al usar esas clases, una clase puede depender de otras clases que deben instanciarse primero.

Entonces, le decimos a Spring que la clase A depende de la clase B. Entonces, al crear un bean (como clase) para la clase A, instancia la clase B antes que la de la clase A y la inyecta en la clase A usando los métodos setter o constructor DI. Es decir, le estamos diciendo a Spring la dependencia en tiempo de ejecución. Este es DI.

Como estamos asignando la responsabilidad de crear objetos (beans), mantenerlos y sus agregaciones en Spring en lugar de codificarlo, lo llamamos Inversión de control (IOC).


7

Inversión de control (IOC):

IoC es un patrón de diseño que describe la inversión del flujo de control en un sistema, por lo que el flujo de ejecución no está controlado por una pieza central de código. Esto significa que los componentes solo deben depender de abstracciones de otros componentes y no son responsables de manejar la creación de objetos dependientes. En su lugar, las instancias de objetos se proporcionan en tiempo de ejecución mediante un contenedor de IoC a través de Dependency Injection (DI).

IoC permite un mejor diseño de software que facilita la reutilización, el acoplamiento flexible y la prueba sencilla de los componentes de software.

Inyección de dependencia (DI):

DI es una técnica para pasar dependencias al constructor de un objeto. Si el objeto se ha cargado desde el contenedor, el contenedor proporcionará automáticamente sus dependencias. Esto le permite consumir una dependencia sin tener que crear manualmente una instancia. Esto reduce el acoplamiento y le brinda un mayor control sobre la vida útil de las instancias de objetos.

haga clic para ver más


6

Spring: Spring es un contenedor de "Inversión de control" para la plataforma Java.

Inversión de control (IoC): La inversión de control (IoC) es una práctica de programación orientada a objetos mediante la cual el acoplamiento de objetos está limitado en tiempo de ejecución por un objeto "ensamblador" y normalmente no se pueden conocer en tiempo de compilación mediante análisis estático.

Inyección de dependencias (DI): "La inyección de dependencias es un patrón de diseño de software que permite la eliminación de dependencias codificadas de forma rígida y hace posible cambiarlas, ya sea en tiempo de ejecución o en tiempo de compilación". -wiki.


¿Cómo es esto más simple de lo que ya está disponible (que es de donde proviene esta respuesta)? No tiene en cuenta la solicitud de simplicidad del OP, a menos que las citas dobles en torno a las terminologías simplifiquen mágicamente las cosas.
Llama de udun

6

Inversión de control: significa dar el control de la creación y instanciación de los beans de primavera al contenedor IOC de Spring y el único trabajo que hace el desarrollador es configurar los beans en el archivo xml de primavera.

Inyección de dependencia-

Considere un empleado de clase

class Employee { 
   private int id;
   private String name;
   private Address address;

   Employee() {
     id = 10;
     name="name";
     address = new Address();
   }


}

y considerar la dirección de la clase

class Address {
   private String street;
   private String city;

   Address() {
     street="test";
     city="test1";

  }
}

En el código anterior, los valores de la clase de dirección se establecerán solo cuando se cree una instancia de la clase Empleado, que es la dependencia de la clase Dirección en la clase Empleado. Y Spring resuelve este problema utilizando el concepto de inyección de dependencia proporcionando dos formas de inyectar esta dependencia.

  1. Inyección de setter

Método de establecimiento en la clase Empleado que toma una referencia de la clase Dirección

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Inyección de constructor

Constructor en la clase de empleado que acepta la dirección

Employee(Address addr) {
      this.address = addr;
}

De esta manera, los valores de la clase de dirección se pueden establecer de forma independiente mediante la inyección de setter / constructor.


3

La inversión de control es un principio de diseño genérico de la arquitectura de software que ayuda a crear marcos de software modulares y reutilizables que son fáciles de mantener.

Es un principio de diseño en el que el flujo de control se "recibe" de la biblioteca genérica escrita o del código reutilizable.

Para entenderlo mejor, veamos cómo solíamos codificar en nuestros primeros días de codificación. En los lenguajes procedimentales / tradicionales, la lógica empresarial generalmente controla el flujo de la aplicación y "llama" al código / funciones genéricos o reutilizables. Por ejemplo, en una aplicación de consola simple, mi flujo de control está controlado por las instrucciones de mi programa, que pueden incluir las llamadas a algunas funciones generales reutilizables.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

En contraste, con IoC, los Frameworks son el código reutilizable que "llama" a la lógica empresarial.

Por ejemplo, en un sistema basado en Windows, ya estará disponible un marco para crear elementos de la interfaz de usuario como botones, menús, ventanas y cuadros de diálogo. Cuando escribo la lógica empresarial de mi aplicación, serían los eventos del framework los que llamarían a mi código de lógica empresarial (cuando se activa un evento) y NO al contrario.

Aunque el código del marco no conoce mi lógica empresarial, aún sabrá cómo llamar a mi código. Esto se logra mediante eventos / delegados, devoluciones de llamada, etc. Aquí el control de flujo está "Invertido".

Entonces, en lugar de depender del flujo de control en objetos vinculados estáticamente, el flujo depende del gráfico de objeto general y las relaciones entre diferentes objetos.

La inyección de dependencia es un patrón de diseño que implementa el principio de IoC para resolver dependencias de objetos.

En palabras más simples, cuando intente escribir código, creará y usará diferentes clases. Una clase (Clase A) puede utilizar otras clases (Clase B y / o D). Entonces, las clases B y D son dependencias de la clase A.

Una simple analogía sería un auto de clase. Un automóvil puede depender de otras clases como motor, neumáticos y más.

La inyección de dependencia sugiere que, en lugar de que las clases dependientes (Class Car aquí) creen sus dependencias (Class Engine y class Tire), la clase debería inyectarse con la instancia concreta de la dependencia.

Entendamos con un ejemplo más práctico. Considere que está escribiendo su propio TextEditor. Entre otras cosas, puede tener un corrector ortográfico que le proporcione al usuario la posibilidad de verificar los errores tipográficos en su texto. Una implementación simple de dicho código puede ser:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

A primera vista, todo parece color de rosa. El usuario escribirá algún texto. El desarrollador capturará el texto y llamará a la función CheckSpellings y encontrará una lista de errores tipográficos que le mostrará al usuario.

Todo parece funcionar muy bien hasta que un buen día un usuario comienza a escribir en francés en el Editor.

Para proporcionar soporte para más idiomas, necesitamos tener más correctores ortográficos. Probablemente francés, alemán, español, etc.

Aquí, hemos creado un código estrechamente acoplado con "English" SpellChecker estrechamente acoplado con nuestra clase TextEditor, lo que significa que nuestra clase TextEditor depende de EnglishSpellChecker o, en otras palabras, EnglishSpellCheker es la dependencia de TextEditor. Necesitamos eliminar esta dependencia. Además, nuestro editor de texto necesita una forma de contener la referencia concreta de cualquier corrector ortográfico según el criterio del desarrollador en tiempo de ejecución.

Entonces, como vimos en la introducción de DI, sugiere que la clase debe inyectarse con sus dependencias. Por lo tanto, debería ser responsabilidad del código de llamada inyectar todas las dependencias a la clase / código llamado. Entonces podemos reestructurar nuestro código como

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

En nuestro ejemplo, la clase TextEditor debería recibir la instancia concreta del tipo ISpellChecker.

Ahora, la dependencia se puede inyectar en Constructor, una Propiedad Pública o un método.

Intentemos cambiar nuestra clase usando Constructor DI. La clase TextEditor modificada se verá así:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Para que el código de llamada, mientras crea el editor de texto, pueda inyectar el tipo de corrector ortográfico apropiado en la instancia del TextEditor.

Puedes leer el artículo completo aquí


1

La forma tradicional de obtener una instancia de dirección en Empleado sería creando una nueva instancia de la clase Dirección. Spring crea todos los objetos dependientes para nosotros, por lo que no debemos preocuparnos por el objeto.

Entonces, en Spring, solo dependemos del contenedor Spring que nos proporciona el objeto de dependencia.


1

IOC es una técnica en la que dejas que otra persona cree el objeto por ti. Y la otra persona en caso de primavera es contenedor IOC.

La inyección de dependencia es una técnica en la que un objeto proporciona la dependencia de otro objeto.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.