

En ingeniería de software , la inyección de dependencias es una técnica de programación en la que un objeto o función recibe otros objetos o funciones que requiere, en lugar de crearlos internamente. La inyección de dependencias busca separar las preocupaciones de construir objetos y usarlos, lo que lleva a programas débilmente acoplados . [ 1 ] [ 2 ] [ 3 ] El patrón asegura que un objeto o función que quiera usar un servicio dado no tenga que saber cómo construir esos servicios. En cambio, el " cliente " receptor (objeto o función) recibe sus dependencias de código externo (un "inyector"), del cual no es consciente. [ 4 ] La inyección de dependencias hace explícitas las dependencias implícitas y ayuda a resolver los siguientes problemas: [ 5 ]
- ¿Cómo puede una clase ser independiente de la creación de los objetos de los que depende?
- ¿Cómo pueden una aplicación y los objetos que utiliza admitir diferentes configuraciones?
La inyección de dependencias se usa a menudo para mantener el código en línea con el principio de inversión de dependencias . [ 6 ] [ 7 ]
En los lenguajes de tipado estático, el uso de la inyección de dependencias implica que un cliente solo necesita declarar las interfaces de los servicios que utiliza, en lugar de sus implementaciones concretas, lo que facilita el cambio de los servicios utilizados en tiempo de ejecución sin necesidad de recompilar.
Los frameworks de aplicaciones suelen combinar la inyección de dependencias con la inversión de control . En la inversión de control, el framework primero construye un objeto (como un controlador) y luego le transfiere el flujo de control . Con la inyección de dependencias, el framework también instancia las dependencias declaradas por el objeto de la aplicación (a menudo en los parámetros del método constructor) y las pasa al objeto. [ 8 ]
La inyección de dependencias implementa la idea de "invertir el control sobre las implementaciones de las dependencias", razón por la cual ciertos frameworks de Java denominan genéricamente al concepto "inversión de control" (que no debe confundirse con la inversión del flujo de control ). [ 9 ]
Roles
Inyección de dependencias para niños de cinco años
Cuando vas a sacar cosas del refrigerador para ti, puedes causar problemas. Podrías dejar la puerta abierta, podrías sacar algo que mamá o papá no quieren que comas. Incluso podrías estar buscando algo que ni siquiera tenemos o que está caducado.
Lo que debes hacer es expresar tu necesidad, por ejemplo: "Necesito algo de beber con el almuerzo", y entonces nos aseguraremos de que tengas algo cuando te sientes a comer.
La inyección de dependencias implica cuatro roles: servicios, clientes, interfaces e inyectores.
Servicios y clientes
Un servicio es cualquier clase que contiene funcionalidad útil. A su vez, un cliente es cualquier clase que utiliza servicios. Los servicios que un cliente requiere son las dependencias del cliente .
Cualquier objeto puede ser un servicio o un cliente; los nombres se refieren únicamente al rol que desempeñan los objetos en una inyección. Un mismo objeto puede incluso ser tanto un cliente (utiliza servicios inyectados) como un servicio (se inyecta en otros objetos). Tras la inyección, el servicio pasa a formar parte del estado del cliente y queda disponible para su uso. [ 12 ]
Interfaces
Los clientes no deberían conocer la implementación de sus dependencias, solo sus nombres y la API . Por ejemplo, un servicio que recupera correos electrónicos puede usar los protocolos IMAP o POP3 internamente, pero este detalle probablemente sea irrelevante para el código que simplemente busca recuperar un correo electrónico. Al ignorar los detalles de implementación, los clientes no necesitan modificar sus dependencias.
Inyectores
El inyector , a veces también llamado ensamblador, contenedor, proveedor o fábrica, introduce servicios al cliente.
La función de los inyectores es construir y conectar grafos de objetos complejos, donde los objetos pueden ser tanto clientes como servicios. El inyector en sí puede estar formado por muchos objetos que trabajan juntos, pero no debe ser el cliente, ya que esto crearía una dependencia circular .
Debido a que la inyección de dependencias separa la forma en que se construyen los objetos de la forma en que se utilizan, a menudo disminuye la importancia de la newpalabra clave presente en la mayoría de los lenguajes orientados a objetos . Dado que el framework se encarga de crear servicios, el programador tiende a construir directamente solo objetos de valor que representan entidades en el dominio del programa (como un Employeeobjeto en una aplicación empresarial o un Orderobjeto en una aplicación de compras). [ 13 ] [ 14 ] [ 15 ] [ 16 ]
Analogía
A modo de analogía, podemos considerar los automóviles como servicios que realizan la útil labor de transportar personas de un lugar a otro. Los motores de los automóviles pueden requerir gasolina , diésel o electricidad , pero este detalle es irrelevante para el cliente —el pasajero— a quien solo le importa que el vehículo lo lleve a su destino.
Los automóviles presentan una interfaz uniforme a través de sus pedales, volantes y demás controles. Por lo tanto, el motor con el que fueron equipados en la fábrica deja de ser relevante, y los conductores pueden cambiar entre cualquier tipo de automóvil según sus necesidades.
Ventajas y desventajas
Ventajas
Una ventaja básica de la inyección de dependencias es la disminución del acoplamiento entre las clases y sus dependencias. [ 17 ] [ 18 ]
Al eliminar el conocimiento del cliente sobre cómo se implementan sus dependencias, los programas se vuelven más reutilizables, comprobables y mantenibles. [ 19 ]
Esto también resulta en una mayor flexibilidad: un cliente puede actuar sobre cualquier cosa que admita la interfaz intrínseca que espera. [ 20 ]
En términos más generales, la inyección de dependencias reduce el código repetitivo , ya que toda la creación de dependencias es manejada por un único componente. [ 19 ]
Finalmente, la inyección de dependencias permite el desarrollo concurrente. Dos desarrolladores pueden desarrollar de forma independiente clases que se utilizan mutuamente, necesitando únicamente conocer la interfaz a través de la cual se comunicarán. Los complementos suelen ser desarrollados por terceros que ni siquiera se comunican con los desarrolladores del producto original. [ 21 ]
Pruebas
Muchos de los beneficios de la inyección de dependencias son particularmente relevantes para las pruebas unitarias .
Por ejemplo, la inyección de dependencias se puede utilizar para externalizar los detalles de configuración de un sistema en archivos de configuración, lo que permite reconfigurar el sistema sin necesidad de recompilación. Se pueden escribir configuraciones separadas para diferentes situaciones que requieren distintas implementaciones de componentes. [ 22 ]
De igual modo, dado que la inyección de dependencias no requiere ningún cambio en el comportamiento del código, se puede aplicar al código heredado como una refactorización . Esto hace que los clientes sean más independientes y facilita las pruebas unitarias de forma aislada, utilizando objetos simulados o ficticios que simulan otros objetos que no se están probando.
Esta facilidad de prueba suele ser el primer beneficio que se observa al utilizar la inyección de dependencias. [ 23 ]
Desventajas
Los críticos de la inyección de dependencias argumentan que:
- Crea clientes que exigen detalles de configuración, lo cual puede ser oneroso cuando existen valores predeterminados obvios. [ 21 ]
- Hace que el código sea difícil de rastrear porque separa el comportamiento de la construcción. [ 21 ]
- Normalmente se implementa con reflexión o programación dinámica, lo que dificulta la automatización del IDE . [ 24 ]
- Por lo general, requiere un mayor esfuerzo de desarrollo inicial. [ 25 ]
- Fomenta la dependencia de un marco. [ 26 ] [ 27 ] [ 28 ]
Tipos de inyección de dependencias
Hay varias formas en que un cliente puede recibir servicios inyectados: [ 29 ]
- Inyección por constructor, donde las dependencias se proporcionan a través del constructor de la clase del cliente .
- Inyección de métodos, donde las dependencias se proporcionan a un método solo cuando son necesarias para una funcionalidad específica.
- Inyección por método setter, donde el cliente expone un método setter que acepta la dependencia.
- Inyección de interfaz, donde la interfaz de la dependencia proporciona un método inyector que inyectará la dependencia en cualquier cliente que se le pase.
En algunos frameworks, los clientes no necesitan aceptar activamente la inyección de dependencias. En Java , por ejemplo, la reflexión puede hacer públicos los atributos privados durante las pruebas e inyectar servicios directamente. [ 30 ]
Sin inyección de dependencias
En el siguiente ejemplo de Java , la Clientclase contiene una Servicevariable miembro inicializada en el constructor . El cliente construye y controla directamente qué servicio utiliza, creando una dependencia codificada.
clase pública Cliente { servicio privado servicio ;Cliente () { // La dependencia está codificada. this . service = new ExampleService (); } }Inyección de constructor
La forma más común de inyección de dependencias consiste en que una clase solicite sus dependencias a través de su constructor . Esto garantiza que el cliente siempre se encuentre en un estado válido, ya que no puede instanciarse sin las dependencias necesarias.
clase pública Cliente { servicio privado servicio ;// La dependencia se inyecta a través de un constructor. Cliente ( Servicio servicio ) { if ( servicio == null ) { throw new IllegalArgumentException ( "el servicio no debe ser nulo" ); } this . servicio = servicio ; } }Evitar los casos únicos
La inyección de dependencias puede utilizarse para evitar el patrón singleton . El patrón singleton impone una restricción estructural de una sola instancia de una clase, pero la inyección de dependencias se centra en cómo se pasan las dependencias, evitando la necesidad de que los objetos consulten su propio estado global. [ 31 ]
Por ejemplo, en el siguiente ejemplo, OrderServiceestá estrechamente acoplado a DatabaseConnection; la base de datos no se puede intercambiar y no se puede utilizar una instancia diferente.
// una clase singleton concreta class DatabaseConnection { private static DatabaseConnection instance ;private DatabaseConnection () { // inicialización de recursos de la base de datos }public static synchronized DatabaseConnection instance () { if ( instance == null ) { instance = new DatabaseConnection (); } return instance ; }public void executeQuery ( String sql ) { System . out . printf ( "Ejecutando: %s%n" ); } }// una clase de consumidor estrechamente acoplada class OrderService { public void placeOrder ( String orderId ) { // la búsqueda de dependencia codificada hace que esto sea imposible de probar unitariamente DatabaseConnection db = DatabaseConnection . instance (); db . executeQuery ( String . format ( "INSERT INTO orders VALUES ('%s')" )); } }La inyección de dependencias evita preguntar cómo se crea la base de datos o cuántas instancias existen, y solo solicita la Databaseinterfaz en su constructor:
// una interfaz abstracta interface Database { void executeQuery ( String sql ) ; }// Implementar la clase concreta (sin lógica singleton) class SqlDatabase implements Database { @Override public void executeQuery ( String sql ) { System . out . println ( "Ejecutando SQL: %s" , sql ); } }// La clase consumidora acepta la dependencia a través de la inyección del constructor. class OrderService { private final Database db ;// La dependencia se inyecta desde el exterior public OrderService ( Database db ) { this . db = db ; }public void placeOrder ( String orderId ) { db . executeQuery ( String . format ( "INSERT INTO orders VALUES ('%s')" , orderId )); } }Método de inyección
Las dependencias se pasan como argumentos a un método específico, lo que permite utilizarlas únicamente durante la ejecución de dicho método sin necesidad de mantener una referencia a largo plazo. Este enfoque resulta especialmente útil para dependencias temporales o cuando se requieren implementaciones diferentes para distintas llamadas a métodos.
public class Client { public void performAction ( Service service ) { if ( service == null ) { throw new IllegalArgumentException ( "service no debe ser nulo" ); } service . execute (); } }Inyección de Setter
Al aceptar las dependencias mediante un método setter , en lugar de un constructor, los clientes pueden permitir que los inyectores manipulen sus dependencias en cualquier momento. Esto ofrece flexibilidad, pero dificulta garantizar que todas las dependencias se inyecten y sean válidas antes de que se utilice el cliente.
clase pública Cliente { servicio privado servicio ;// La dependencia se inyecta a través de un método setter. public void setService ( Service service ) { if ( service == null ) { throw new IllegalArgumentException ( "service no debe ser nulo" ); } this . service = service ; } }Inyección de interfaz
Con la inyección de interfaz, las dependencias desconocen por completo a sus clientes, pero aun así envían y reciben referencias a nuevos clientes.
De esta forma, las dependencias se convierten en inyectores. La clave reside en que el método de inyección se proporciona a través de una interfaz.
Aún se necesita un ensamblador para introducir el cliente y sus dependencias. El ensamblador toma una referencia al cliente, la convierte a la interfaz setter que establece esa dependencia y la pasa a ese objeto de dependencia, que a su vez pasa una referencia a sí mismo de vuelta al cliente.
Para que la inyección de interfaz tenga valor, la dependencia debe realizar alguna acción adicional además de simplemente devolver una referencia a sí misma. Esto podría consistir en actuar como una fábrica o subensamblador para resolver otras dependencias, abstraiendo así algunos detalles del ensamblador principal. También podría ser un sistema de conteo de referencias para que la dependencia sepa cuántos clientes la están utilizando. Si la dependencia mantiene una colección de clientes, podría posteriormente inyectarles a todos una instancia diferente de sí misma.
paquete org.wikipedia.examples ;importar java.util.HashSet ; importar java.util.Set ;interface ServiceSetter { void setService ( Service service ); }clase Cliente implementa ServiceSetter { private Service servicio ;@Override public void setService ( Service service ) { if ( service == null ) { throw new IllegalArgumentException ( "service no debe ser nulo" ); } this . service = service ; } }clase ServiceInjector { private final Set < ServiceSetter > clientes = new HashSet <> ();public void inject ( ServiceSetter client ) { this.clients.add ( client ) ; client.setService ( new ExampleService ( ) ) ; }public void switch () { for ( Client client : this . clients ) { client . setService ( new AnotherExampleService ()); } } }clase ExampleService implementa Service {}clase AnotherExampleService implementa Service {}Asamblea
La forma más sencilla de implementar la inyección de dependencias es organizar manualmente los servicios y los clientes, lo que normalmente se hace en la raíz del programa, donde comienza la ejecución.
public class Program { public static void main ( String [] args ) { // Construir el servicio. Service service = new ExampleService ();// Inyecta el servicio en el cliente. Cliente cliente = nuevo Cliente ( servicio );// Usar los objetos. System.out.println ( cliente.greet ( ) ) ; } }La construcción manual puede ser más compleja e involucrar a constructores , fábricas u otros métodos de construcción .
Marcos de trabajo

La inyección manual de dependencias suele ser tediosa y propensa a errores en proyectos grandes, lo que fomenta el uso de frameworks que automatizan el proceso. La inyección manual de dependencias se convierte en un framework de inyección de dependencias cuando el código de construcción deja de ser específico de la aplicación y se vuelve universal. [ 32 ] Si bien son útiles, estas herramientas no son necesarias para realizar la inyección de dependencias. [ 33 ] [ 34 ]
En Java, históricamente Java EE proporcionaba un marco de inyección de dependencias bajo javax.inject; ahora lo proporciona Jakarta EE como jakarta.inject, con la jakarta.inject.Provider<T>interfaz para obtener instancias de T, y las siguientes anotaciones : [ 35 ]
@Inject, para marcar constructores, métodos y campos inyectables@Named, para marcar un calificador basado en cadena@Qualifier, para marcar anotaciones de calificadores@Scope, para marcar anotaciones de alcance@Singleton, para marcar un tipo sujeto al patrón singleton por el inyector
En .NET (como C# ), la Microsoft.Extensions.DependencyInjectionbiblioteca es un marco de trabajo incluido dentro de .NET. [ 36 ]
Algunos frameworks, como Spring , pueden utilizar archivos de configuración externos para planificar la composición del programa:
paquete org.wikipedia.examples ;import org.springframework.beans.factory.BeanFactory ; import org.springframework.context.ApplicationContext ; import org.springframework.context.support.ClassPathXmlApplicationContext ;public class Injector { public static void main ( String [] args ) { // Los detalles sobre qué servicio concreto usar se almacenan en la configuración separada del propio programa. BeanFactory beanfactory = new ClassPathXmlApplicationContext ( "Beans.xml" ); Client client = ( Client ) beanfactory . getBean ( "client" ); System . out . println ( client . greet ()); } }Incluso con un grafo de objetos potencialmente largo y complejo, la única clase mencionada en el código es el punto de entrada, en este caso Client. Clientno ha sufrido ningún cambio para funcionar con Spring y sigue siendo un POJO . [ 37 ] [ 38 ] [ 39 ] Al evitar que las anotaciones y llamadas específicas de Spring se dispersen entre muchas clases, el sistema permanece solo débilmente dependiente de Spring. [ 27 ]
Ejemplos
Angular
El siguiente ejemplo muestra un componente de Angular que recibe un servicio de saludo mediante inyección de dependencias:
/* greeter.service.ts */ import { Injectable , inject } from '@angular/core' ; import { DOCUMENT } from '@angular/common' ;export interface IGreeterService { greet ( text : string ) : void ; }@Injectable ({ providedIn : 'root' }) export class GreeterService implements IGreeterService { // Usa inject(DOCUMENT) y accede a defaultView para obtener el objeto Window private window : Window = inject ( DOCUMENT ). defaultView as Window ;saludar ( texto : cadena ) : void { this . window . alert ( texto ); } }<!-- my-controller.component.html --> < div > < button ( click )=" sayHello ()" > Hola </ button > </ div >/* my-controller.component.ts */ import { GreeterService } from './greeter.service.ts' ; import { Component , inject } from '@angular/core' ; @Component ({ selector : 'app-my-controller' , template : 'my-controller.component.html' }) export class MyControllerComponent {privado greeter = inyectar ( GreeterService );sayHello () : void { this.greeter.greet ( ' Hola Mundo ' ) ; } }La injectfunción activa el inyector para crear una instancia del objeto GreeterServicey sus dependencias (en este caso, una Documentinstancia para acceder al windowobjeto).
C++
Este ejemplo proporciona una muestra de inyección de constructor en C++ .
importar std ;clase DatabaseConnection { public : void connect () { std :: println ( "Conectando con la base de datos..." ); } };clase DatabaseService { private : DatabaseConnection & dbConn ; public : explicit DatabaseService ( DatabaseConnection & db ) : dbConn { db } {}void execute () { dbConn . connect (); std :: println ( "Ejecutando servicio de base de datos..." ); } };int main ( int argc , char * argv []) { DatabaseConnection db ; DatabaseService sv ( db ); sv.execute ( ) ; }Este ejemplo proporciona una muestra de inyección de interfaz en C++.
importar std ;using std :: expected ; using std :: shared_ptr ; using std :: unexpected ;clase IConnection { public : enum class Error { NO_CONNECTION , // más errores aquí };virtual void connect () = 0 ; virtual ~ IConnection () = default ; };clase DatabaseConnection : public IConnection { public : DatabaseConnection () = default ;void connect () override { std :: println ( "Conectando con la base de datos..." ); } };clase DatabaseService { private : shared_ptr <IConnection> conn ; public : DatabaseService ( ) = default ;void setConnection ( shared_ptr < IConnection > nextConn ) noexcept { conn = nextConn ; }expected < void , IConnection :: Error > execute () { if ( conn ) { conn -> connect (); std :: println ( "Ejecutando servicio de base de datos..." ); } else { return unexpected ( IConnection :: Error :: NO_CONNECTION ); } } };int main ( int argc , char * argv [ ] ) { shared_ptr <DatabaseConnection> db = std :: make_shared <DatabaseConnection> ( ) ; DatabaseService sv ; sv.setConnection ( db ) ; sv.execute ( ) ; }DO#
Este ejemplo proporciona una muestra de inyección de constructor en C# .
espacio de nombres Wikipedia.Ejemplos ;usando el sistema ;// Nuestro cliente solo conocerá esta interfaz, no qué mando específico está utilizando. interface IGamePadFunctionality { string GetGamePadName (); void SetVibrationPower ( float power ); }// Los siguientes servicios proporcionan implementaciones concretas de la interfaz anterior.clase XboxGamePad : IGamePadFunctionality { float vibrationPower = 1.0f ; public string GetGamePadName () => "Controlador Xbox" ; public void SetVibrationPower ( float power ) => this . vibrationPower = Math . Clamp ( power , 0.0f , 1.0f ); }clase PlayStationJoystick : IGamePadFunctionality { float vibratingPower = 100.0f ; public string GetGamePadName () => "Controlador de PlayStation" ; public void SetVibrationPower ( float power ) => this . vibratingPower = Math . Clamp ( power * 100.0f , 0.0f , 100.0f ); }clase SteamController : IGamePadFunctionality { double vibrating = 1.0 ; public string GetGamePadName () => "Controlador Steam" ; public void SetVibrationPower ( float power ) => this . vibrating = Convert . ToDouble ( Math . Clamp ( power , 0.0f , 1.0f )); }// Esta clase es el cliente que recibe un servicio. class GamePad { IGamePadFunctionality gamePadFunctionality ;// El servicio se inyecta a través del constructor y se almacena en el campo anterior. public GamePad ( IGamePadFunctionality gamePadFunctionality ) => this . gamePadFunctionality = gamePadFunctionality ;public void Showcase () { // Se utiliza el servicio inyectado. string gamePadName = this.gamePadFunctionality.GetGamePadName ( ); string message = $"Estamos usando el {gamePadName} ahora mismo, ¿ quieres cambiar la potencia de vibración ? " ; Console.WriteLine ( message ) ; } }class Program { static void Main ( string [] args ) { SteamController steamController = new (); // También podríamos haber pasado un XboxController, PlayStationJoystick, etc. // El mando no sabe qué está usando y no necesita saberlo. GamePad gamepad = new ( steamController ); gamepad . Showcase (); } }Ir
Go no admite clases y, por lo general, la inyección de dependencias se abstrae mediante una biblioteca dedicada que utiliza reflexión o genéricos (estos últimos compatibles desde Go 1.18 [ 40 ] ). [ 41 ] Un ejemplo más sencillo sin utilizar bibliotecas de inyección de dependencias se ilustra con el siguiente ejemplo de una aplicación web MVC .
Primero, pasa las dependencias necesarias a un enrutador y luego del enrutador a los controladores:
enrutador de paquetesimport ( "database/sql" "net/http""ejemplo/controladores/usuarios""github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware""github.com/redis/go-redis/v9" "github.com/rs/zerolog" )type RoutingHandler struct { // pasar los valores por puntero más abajo en la pila de llamadas // significa que no crearemos una nueva copia, ahorrando memoria log * zerolog . Logger db * sql . DB cache * redis . Client router chi . Router }// La conexión, el registrador y la caché se inicializan normalmente en la función principal func NewRouter ( log * zerolog . Logger , db * sql . DB , cache * redis . Client , ) ( r * RoutingHandler ) { rtr := chi . NewRouter ()return & RoutingHandler { log : log , db : db , cache : cache , router : rtr , } }func ( r * RoutingHandler ) SetupUsersRoutes () { uc := users . NewController ( r . log , r . db , r . cache )r . router . Get ( "/users/:name" , func ( w http . ResponseWriter , r * http . Request ) { uc . Get ( w , r ) }) }De esta forma, se puede acceder a los campos privados de la estructura en cualquier método que sea su receptor de puntero , sin violar la encapsulación.
usuarios del paqueteimport ( "database/sql" "net/http""ejemplos/modelos""github.com/go-chi/chi/v5" "github.com/redis/go-redis/v9" "github.com/rs/zerolog" )tipo Controller struct { log * zerolog . Logger storage models . UserStorage cache * redis . Client }func NewController ( log * zerolog . Logger , db * sql . DB , cache * redis . Client ) * Controller { return & Controller { log : log , storage : models . NewUserStorage ( db ), cache : cache , } }func ( uc * Controller ) Get ( w http . ResponseWriter , r * http . Request ) { // tenga en cuenta que también podemos envolver el registro en un middleware, esto es para fines de demostración uc . log . Info (). Msg ( "Obteniendo usuario" )parámetro de usuario : = chi . URLParam ( r , "nombre" )var user * models . User // obtener el usuario de la caché err := uc . cache . Get ( r . Context (), userParam ). Scan ( & user ) if err != nil { uc . log . Error (). Err ( err ). Msg ( "Error al obtener el usuario de la caché. Recuperando del almacenamiento SQL" ) }usuario , err = uc.storage.Get ( r.Context ( ) , " johndoe" ) if err ! = nil { uc.log.Error ( ) . Err ( err ) .Msg ( " Error al obtener el usuario del almacenamiento SQL" ) http.Error ( w , " Error interno del servidor " , http.StatusInternalServerError ) return } }Finalmente, la conexión a la base de datos inicializada en la función principal se puede utilizar en la capa de acceso a datos:
modelos de paquetesimport ( "database/sql" "time" )tipo ( UserStorage struct { conn * sql . DB }Estructura de usuario { Nombre cadena ' json : "nombre" db : "nombre,claveprimaria" ' UnidoEn tiempo . Tiempo ' json : "unido_en" db : "unido_en" ' Correo electrónico cadena ' json : "correo electrónico" db : "correo electrónico" ' } )func NewUserStorage ( conn * sql . DB ) * UserStorage { return & UserStorage { conn : conn , } }func ( us * UserStorage ) Get ( name string ) ( user * User , err error ) { // suponiendo que 'name' es una clave única query := "SELECT * FROM users WHERE name = $1"if err := us . conn . QueryRow ( query , name ). Scan ( & user ); err != nil { return nil , err }devolver usuario , nil }Óxido
En Rust , la inyección de dependencias se realiza normalmente a través de genéricos con despacho estático .
trait Logger { fn log ( & self , mensaje : & str ); }struct ConsoleLogger ;impl Logger para ConsoleLogger { fn log ( & self , message : & str ) { println! ( "{message}" ); } }struct UserService < L : Logger > { logger : L , }impl < L : Logger > UserService < L > { fn new ( logger : L ) -> Self { Self { logger } }fn create_user ( & self , name : & str ) { self . logger . log ( & format! ( "Creando usuario: {name}" )); // Lógica de negocio... } }fn main () { let logger = ConsoleLogger ; let service = UserService :: new ( logger );servicio.create_user ( "Alice " ) ; }Sin embargo, también se puede hacer utilizando el despacho dinámico con objetos de rasgos:
trait Logger { fn log ( & self , mensaje : & str ); }struct ConsoleLogger ;impl Logger para ConsoleLogger { fn log ( & self , message : & str ) { println! ( "{message}" ); } }struct UserService { logger : Box < dyn Logger > , }impl UserService { fn new ( logger : Box < dyn Logger > ) -> Self { Self { logger } }fn create_user ( & self , name : & str ) { self . logger . log ( & format! ( "Creando usuario: {name}" )); } }fn main () { let logger = Box :: new ( ConsoleLogger ); let service = UserService :: new ( logger );servicio.create_user ( "Alice " ) ; }Véase también
Referencias
- ↑ Seemann, Mark. "La inyección de dependencias es un acoplamiento flexible" . blog.ploeh.dk . Consultado el 28 de julio de 2015 .
- 1 2 Seeman, Mark (octubre de 2011). Inyección de dependencias en .NET . Manning Publications. pág. 4. ISBN 9781935182504.
- ↑ Niko Schwarz, Mircea Lungu, Oscar Nierstrasz, "Seuss: Desacoplamiento de responsabilidades de métodos estáticos para una configurabilidad de grano fino", Journal of Object Technology, volumen 11, n.º 1 (abril de 2012), págs. 3:1–23.
- ↑ "HollywoodPrinciple" . c2.com . Consultado el 19 de julio de 2015 .
- ↑ "El patrón de diseño de inyección de dependencias : problema, solución y aplicabilidad" . w3sDesign.com . Consultado el 12 de agosto de 2017 .
- ↑ Erez, Guy (2022-03-09). "Inversión de dependencias vs. Inyección de dependencias" . Medium . Recuperado el 2022-12-06 .
- ↑ Mathews, Sasha (25-03-2021). "Simplemente estás inyectando una dependencia, pensando que estás siguiendo la inversión de dependencia..." Medium . Recuperado el 06-12-2022 .
- ↑ "Contenedor IoC de Spring" . Consultado el 23 de mayo de 2023 .
- ↑ Fowler, Martin. "Contenedores de inversión de control y el patrón de inyección de dependencias" . MartinFowler.com . Consultado el 4 de junio de 2023 .
- ↑ "Inyección de dependencias en .NET" (PDF) . philkildea.co.uk . pág. 4. Archivado del original (PDF) el 21/07/2015 . Consultado el 18/07/2015 .
- ↑ "¿Cómo explicar la inyección de dependencias a un niño de 5 años?" . stackoverflow.com . Consultado el 18 de julio de 2015 .
- ↑ IT, Titanium. "James Shore: Desentrañando la inyección de dependencias" . www.jamesshore.com . Consultado el 18 de julio de 2015 .
- ↑ "Ser "nuevo" o no ser "nuevo"... Archivado del original el 13 de mayo de 2020. Recuperado el 18 de julio de 2015 .
- ↑ "Cómo escribir código comprobable" . www.loosecouplings.com . Consultado el 18 de julio de 2015 .
- ↑ "Cómo escribir código limpio y comprobable" . www.ethanresnick.com . Consultado el 18 de julio de 2015 .
- ↑ Sironi, Giorgio. "Cuándo inyectar: la distinción entre nuevos e inyectables - Invisible a simple vista" . www.giorgiosironi.com . Consultado el 18 de julio de 2015 .
- ↑ "El canadiense urbano, ¿eh?: Sobre la inyección de dependencias y la violación de las preocupaciones sobre la encapsulación" . www.bryancook.net . Consultado el 18 de julio de 2015 .
- ↑ "El patrón de diseño de inyección de dependencias" . msdn.microsoft.com . Consultado el 18 de julio de 2015 .
- 1 2 "El programa Java Community Process(SM) - JSRs: Java Specification Requests - detalle JSR# 330" . jcp.org . Consultado el 18 de julio de 2015 .
- ↑ "3.1. Inyección de dependencias — Python 3: de la nada al aprendizaje automático" . Archivado del original el 8 de febrero de 2020.
- 1 2 3 "Cómo funciona la inyección de dependencias (DI) en el desarrollo de aplicaciones Java con Spring - DZone Java" .
- ↑ "Inyección de dependencias e inversión de control en Python — Documentación de Dependency Injector 4.36.2" .
- ↑ "Cómo refactorizar para la inyección de dependencias, parte 3: aplicaciones más grandes" .
- ↑ "Una breve introducción a la inyección de dependencias: qué es y cuándo usarla" . 18 de octubre de 2018.
- ↑ "Inyección de dependencias | Professionalqa.com" .
- ↑ "¿Cuáles son las desventajas de usar la inyección de dependencias?" . stackoverflow.com . Consultado el 18 de julio de 2015 .
- 1 2 "Inversión de inyección de dependencias – Clean Coder" . sites.google.com . Consultado el 18 de julio de 2015 .
- ↑ "Desacoplando su aplicación de su marco de inyección de dependencias" . InfoQ . Consultado el 18 de julio de 2015 .
- ↑ Martin Fowler (23 de enero de 2004). "Contenedores de inversión de control y el patrón de inyección de dependencias: formas de inyección de dependencias" . Martinfowler.com . Consultado el 22 de marzo de 2014 .
- ↑ "AccessibleObject (Java Platform SE 7)" . docs.oracle.com . Consultado el 18 de julio de 2015 .
- ↑ Microsoft Learn (11 de marzo de 2026). "Directrices sobre inyección de dependencias" . learn.microsoft.com . Microsoft Learn.
- ↑ Riehle, Dirk (2000), Diseño de marcos: un enfoque de modelado de roles (PDF) , Instituto Federal Suizo de Tecnología
- ↑ "Inyección de dependencias ≠ usar un contenedor DI" . www.loosecouplings.com . Consultado el 18 de julio de 2015 .
- ↑ "Black Sheep » DIY-DI » Print" . blacksheep.parry.org . Archivado del original el 27 de junio de 2015. Consultado el 18 de julio de 2015 .
- ^ Yakarta EE (16 de octubre de 2021). "Paquete jakarta.inject" . jakarta.ee . Yakarta EE.UU.
- ↑ Microsoft Learn. "Espacio de nombres Microsoft.Extensions.DependencyInjection" . learn.microsoft.com . Microsoft Learn . Consultado el 6 de julio de 2026 .
- ↑ "Consejos de primavera: Un POJO con anotaciones no es simple" . Archivado del original el 15 de julio de 2015. Consultado el 18 de julio de 2015 .
- ↑ "Anotaciones en POJO: ¿una bendición o una maldición? | Techtracer" . 7 de abril de 2007. Consultado el 18 de julio de 2015 .
- ↑ Módulos dinámicos Pro Spring para plataformas de servicios OSGi . APress. 17 de febrero de 2009. ISBN 9781430216124. Consultado el 6 de julio de 2015 .
- ↑ "Notas de la versión 1.18 de Go - El lenguaje de programación Go" . go.dev . Consultado el 17 de abril de 2024 .
- ↑ "Awesome Go – inyección de dependencias" . Github . 17 de abril de 2024. Consultado el 17 de abril de 2024 .
Enlaces externos
- Raíz de composición de Mark Seemann
- Guía para principiantes sobre la inyección de dependencias
- Inyección de dependencias y objetos comprobables: Diseño de objetos débilmente acoplados y comprobables - Jeremy Weiskotten; Dr. Dobb's Journal , mayo de 2006.
- Patrones de diseño: Inyección de dependencias - Revista MSDN, septiembre de 2005
- El artículo original de Martin Fowler que introdujo el término Inyección de Dependencias
- P de EAA: Plugin
- La rica herencia de ingeniería detrás de la inyección de dependencias - Andrew McVeigh - Una historia detallada de la inyección de dependencias.
- ¿Qué es la inyección de dependencias? - Una explicación alternativa - Jakob Jenkov
- Cómo escribir código más fácil de probar con inyección de dependencias -- Developer.com, octubre de 2006. Archivado el 11 de marzo de 2008 en Wayback Machine.
- Descripción general del marco de extensibilidad administrada (MSDN)
- Descripción anticuada del Mecanismo de Dependencia por Hunt 1998
- Refactoriza tu código para convertirlo en un contenedor de inyección de dependencias.
- Comprender la inyección de dependencias en PHP
- No necesitas un contenedor de inyección de dependencias.