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?
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?
Respuestas:
Por ejemplo : supongamos que tenemos un objeto Employee
y tiene una dependencia del objeto Address
. Definiríamos un bean correspondiente al Employee
que definirá su dependencia del objeto Address
.
Cuando Spring intente crear un Employee
objeto, verá que Employee
tiene una dependencia de Address
, por lo que primero creará el Address
objeto (objeto dependiente) y luego lo inyectará en el Employee
objeto.
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.
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.
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).
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.
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.
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.
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;
}
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.
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í
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.