Qué es
la Inyección de Dependencia: La Inyección de Dependencia es la funcionalidad principal proporcionada por Spring IOC (Inversion of Control). El módulo Spring-Core es responsable de inyectar dependencias a través de los métodos Constructor o Setter. El principio de diseño de Inversion of Control hace hincapié en mantener las clases de Java independientes entre sí y el contenedor las libera de la creación y el mantenimiento de objetos. Estas clases, administradas por Spring , deben cumplir con la definición estándar de Java-Bean. La Inyección de Dependencia en Spring también asegura un bajo acoplamiento entre las clases.
Necesidad de inyección de dependencia:
Supongamos que la clase Uno necesita el objeto de la clase Dos para instanciar u operar un método, entonces se dice que la clase Uno esdependiente de la clase Dos. Ahora bien, aunque podría parecer correcto depender de un módulo del otro, en el mundo real, esto podría generar muchos problemas, incluida la falla del sistema. Por lo tanto, tales dependencias deben evitarse.
Spring IOC resuelve tales dependencias con Dependency Injection, lo que hace que el código sea más fácil de probar y reutilizar . El acoplamiento flexible entre clases puede ser posible mediante la definición de interfaces para una funcionalidad común y el inyector instanciará los objetos de la implementación requerida. La tarea de crear instancias de objetos la realiza el contenedor de acuerdo con las configuraciones especificadas por el desarrollador.
Tipos de inyección de dependencia de resorte:
Hay dos tipos de Spring Dependency Injection. Están:
- Setter Dependency Injection (SDI) : Este es el más simple de los dos métodos DI. En esto, el DI se inyectará con la ayuda de métodos setter y/o getter. Ahora, para establecer el DI como SDI en el bean, se hace a través del archivo de configuración del bean. Para esto, la propiedad que se establecerá con el SDI se declara bajo la etiqueta <property> en el archivo bean-config.
Ejemplo: digamos que hay una clase GFG que usa SDI y establece la propiedad geeks. El código para ello se da a continuación.
Java
package com.geeksforgeeks.org; import com.geeksforgeeks.org.IGeek; public class GFG { // The object of the interface IGeek IGeek geek; // Setter method for property geek public void setGeek(IGeek geek) { this.geek = geek; } }
- Configurando el SDI en el archivo bean-config:
XML
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="GFG" class="com.geeksforgeeks.org.GFG"> <property name="geek"> <ref bean="CsvGFG" /> </property> </bean> <bean id="CsvGFG" class="com.geeksforgeeks.org.impl.CsvGFG" /> <bean id="JsonGFG" class="com.geeksforgeeks.org.impl.JsonGFG" /> </beans>
- Esto inyecta el bean ‘CsvGFG’ en el objeto ‘GFG’ con la ayuda de un método setter (‘setGeek’)
- Inyección de dependencia del constructor (CDI) : en esto, el DI se inyectará con la ayuda de constructores . Ahora, para establecer el DI como CDI en el bean, se hace a través del archivo de configuración del bean. Para esto, la propiedad que se establecerá con el CDI se declara bajo la etiqueta <constructor-arg> en el archivo bean-config.
Ejemplo: Tomemos el mismo ejemplo de SDI
Java
package com.geeksforgeeks.org; import com.geeksforgeeks.org.IGeek; public class GFG { // The object of the interface IGeek IGeek geek; // Constructor to set the CDI GFG(IGeek geek) { this.geek = geek; } }
- Configuración del CDI en el archivo bean-config:
XML
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="GFG" class="com.geeksforgeeks.org.GFG"> <constructor-arg> <bean class="com.geeksforgeeks.org.impl.CsvGFG" /> </constructor-arg> </bean> <bean id="CsvGFG" class="com.geeksforgeeks.org.impl.CsvGFG" /> <bean id="JsonGFG" class="com.geeksforgeeks.org.impl.JsonGFG" /> </beans>
- Esto inyecta el bean ‘CsvGFG’ en el objeto ‘GFG’ con la ayuda de un constructor.
Inyección de dependencia de setter (SDI) frente a inyección de dependencia de constructor (CDI)
Setter DI | Constructor DI |
---|---|
Mala legibilidad ya que agrega muchos códigos de placa de caldera en la aplicación. | Buena legibilidad ya que está presente por separado en el código. |
El bean debe incluir métodos getter y setter para las propiedades. | La clase de bean debe declarar un constructor coincidente con argumentos. De lo contrario, se lanzará BeanCreationException. |
Requiere la adición de la anotación @Autowired, arriba del setter en el código y, por lo tanto, aumenta el acoplamiento entre la clase y el contenedor DI. | Mejor en el caso de un acoplamiento flexible con el contenedor DI, ya que ni siquiera es necesario agregar la anotación @Autowired en el código. ( Inyecciones de constructor implícitas para escenarios de un solo constructor después de la primavera 4.0 ) |
Las dependencias circulares o las dependencias parciales resultan con Setter DI porque la creación de objetos ocurre antes de las inyecciones. | No hay margen para la dependencia circular o parcial porque las dependencias se resuelven antes de la propia creación del objeto. |
Opción preferida cuando las propiedades son menores y se pueden crear objetos mutables. | Opción preferida cuando las propiedades en el bean son más y los objetos inmutables (por ejemplo, procesos financieros) son importantes para la aplicación. |
Ejemplo de Primavera DI:
- Hemos usado tres clases y una interfaz como beans para ejemplificar los conceptos de CDI y SDI. Son las clases Vehicle, ToyotaEngine, Tires y la interfaz IEngine respectivamente.
- De nuestro ejemplo, podemos ver que la clase Vehicle depende de la implementación del Engine, que es una interfaz. (Entonces, básicamente, un fabricante de vehículos quiere un motor estándar que cumpla con las normas de emisión indias). La clase ToyotaEngine implementa la interfaz y su referencia se proporciona en el archivo de configuración de bean asignado a una de las propiedades de la clase de vehículos.
- En la clase Vehicle, invocamos el contexto de la aplicación y se ejecuta la instanciación del bean. Se instancian dos objetos de la clase Vehicle. Se crea una instancia de ‘obj1’ mediante un bean con el nombre InjectwithConstructor . El nombre del bean podría estar ubicado en el archivo de configuración del bean. De manera similar, se crea una instancia de ‘obj2’ mediante un bean con el nombre InjectwithSetter .
- Se puede observar que ‘obj1’ se inyecta a través del constructor y ‘obj2’ usa la inyección de setter.
- En el archivo de configuración de bean a continuación, hemos utilizado dos declaraciones de beans de vehículo.
- El bean InjectwithConstructor hace uso del elemento constructor-arg, con los atributos name y ref. El atributo ‘Nombre’ se correlaciona con el nombre del argumento del constructor dado en la definición de la clase Vehículo. Y el atributo ‘ref’ apunta a la referencia del bean que se puede usar para inyectar.
- InjectwithSetter utiliza el elemento de propiedad para proporcionar el ‘nombre’ de la propiedad y el ‘valor’ de la propiedad. En lugar del valor, el atributo ‘ref’ se puede usar para denotar una referencia a un bean.
- En los detalles de configuración, estamos inyectando la referencia de ToyotaBean en la referencia de IEngine en el constructor-arg de la clase Vehicle, donde IEngine es una interfaz y necesita una referencia de clase de implementación para la inyección de beans.
- Hemos usado dos referencias de bean separadas para la clase Tires, para inyectar a través de setter y constructor respectivamente. Podemos observar que ‘tyre1Bean’ y ‘tyre2Bean’ se inicializan con valores literales de string para cada una de las propiedades.
<dependencies>
<!-- https:// mvnrepository.com/artifact
/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!-- https:// mvnrepository.com/artifact
/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
</dependencies>
interface IEngine {
String EMISSION_NORMS = "BSIV";
String importOrigin();
double cost();
}
public class ToyotaEngine implements IEngine {
String company;
double cost;
public double getCost()
{
return cost;
}
public void setCost(double cost)
{
cost = this.cost;
}
public String getCompany()
{
return company;
}
public void setCompany(String company)
{
this.company = company;
}
@Override
public String importOrigin()
{
return "Japan";
}
@Override
public double cost()
{
return cost;
}
@Override
public String toString()
{
return "This is Engine object from: "
+ company;
}
}
public class Tyres {
String name;
String place;
String message;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getPlace()
{
return place;
}
public void setPlace(String place)
{
this.place = place;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
@Override
public String toString()
{
return "This is Tyre object: "
+ name + " " + place
+ " " + message;
}
}
public class Vehicle {
IEngine engine;
Tyres tyre;
public Tyres getTyre()
{
return tyre;
}
public void setTyre(Tyres tyre)
{
System.out.println("tyre instantiated via setter");
this.tyre = tyre;
}
public Vehicle(IEngine engine, Tyres tyre)
{
System.out.println("instantiated via constructor");
this.engine = engine;
this.tyre = tyre;
}
public Vehicle() {}
public IEngine getEngine()
{
return engine;
}
public void setEngine(IEngine engine)
{
System.out.println("instantiated via setter");
this.engine = engine;
}
@Override
public String toString()
{
return engine + " " + tyre;
}
public static void main(String a[])
{
ApplicationContext rootctx
= new ClassPathXmlApplicationContext(
"springContext.xml");
// Instantiating the obj1 via Constructor DI
Vehicle obj1
= (Vehicle)rootctx
.getBean("InjectwithConstructor");
// Instantiating the obj1 via Setter DI
Vehicle obj2
= (Vehicle)rootctx
.getBean("InjectwithSetter");
System.out.println(obj1);
System.out.println(obj2);
System.out.println(obj1 == obj2);
}
}
< bean id="tyre1Bean" class="com.techgene.Tyres">
<property name="name" value="MRF">
</ property>
<property name="place" value="India">
</ property>
<property name="message" value="Make in India">
</ property>
</ bean>
< bean id="ToyotaBean" class="com.techgene.ToyotaEngine">
<property name="company" value="Toyota">
</ property>
<property name="cost" value="300000.00">
</ property>
</ bean>
< bean id="tyre2Bean" class="com.techgene.Tyres">
<property name="name" value="TVS">
</ property>
<property name="place" value="India">
</ property>
<property name="message" value="Make in India">
</ property>
</ bean>
< bean id="InjectwithSetter" class="com.techgene.Vehicle">
<property name="engine" ref="ToyotaBean">
</ property>
<property name="tyre" ref="tyre1Bean">
</ property>
</ bean>
< bean id="InjectwithConstructor" class="com.techgene.Vehicle">
<constructor - arg name="engine" ref="ToyotaBean">
</ constructor - arg>
<constructor - arg name="tyre" ref="tyre2Bean">
</ constructor - arg>
</ bean>
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA