Já houve várias perguntas postadas com perguntas específicas sobre injeção de dependência , como quando usá-lo e quais estruturas existem para ele. Contudo,
O que é injeção de dependência e quando / por que deveria ou não deveria ser usada?
Já houve várias perguntas postadas com perguntas específicas sobre injeção de dependência , como quando usá-lo e quais estruturas existem para ele. Contudo,
O que é injeção de dependência e quando / por que deveria ou não deveria ser usada?
Respostas:
Injeção de Dependência está passando a dependência para outros objetos ou estrutura (injetor de dependência).
A injeção de dependência facilita o teste. A injeção pode ser feita através do construtor .
SomeClass()
tem seu construtor da seguinte maneira:
public SomeClass() {
myObject = Factory.getObject();
}
Problema : Se myObject
envolver tarefas complexas, como acesso ao disco ou à rede, é difícil realizar testes de unidade SomeClass()
. Os programadores precisam zombar myObject
e podem interceptar a chamada de fábrica.
Solução alternativa :
myObject
como um argumento para o construtorpublic SomeClass (MyClass myObject) {
this.myObject = myObject;
}
myObject
pode ser passado diretamente, o que facilita o teste.
É mais difícil isolar componentes em testes de unidade sem injeção de dependência.
Em 2013, quando escrevi esta resposta, esse era um tema importante no Blog de testes do Google . Essa continua sendo a maior vantagem para mim, pois os programadores nem sempre precisam de flexibilidade extra em seu design em tempo de execução (por exemplo, para localizador de serviço ou padrões semelhantes). Os programadores geralmente precisam isolar as classes durante o teste.
A melhor definição que encontrei até agora é uma de James Shore :
"Injeção de dependência" é um termo de 25 dólares para um conceito de 5 centavos. [...] Injeção de dependência significa atribuir a um objeto suas variáveis de instância. [...]
Há um artigo de Martin Fowler que também pode ser útil.
A injeção de dependência consiste basicamente em fornecer os objetos de que um objeto precisa (suas dependências), em vez de fazê-lo ele mesmo. É uma técnica muito útil para testes, pois permite que as dependências sejam zombadas ou eliminadas.
Dependências podem ser injetadas em objetos de várias formas (como injeção de construtor ou injeção de setter). Pode-se até usar estruturas especializadas de injeção de dependência (por exemplo, Spring) para fazer isso, mas elas certamente não são necessárias. Você não precisa dessas estruturas para ter injeção de dependência. Instanciar e passar objetos (dependências) explicitamente é uma injeção tão boa quanto a injeção por estrutura.
Encontrei este exemplo engraçado em termos de acoplamento flexível :
Qualquer aplicativo é composto de muitos objetos que colaboram entre si para executar algumas coisas úteis. Tradicionalmente, cada objeto é responsável por obter suas próprias referências aos objetos dependentes (dependências) com os quais ele colabora. Isso leva a classes altamente acopladas e código difícil de testar.
Por exemplo, considere um Car
objeto.
A Car
depende das rodas, motor, combustível, bateria, etc. para funcionar. Tradicionalmente, definimos a marca de tais objetos dependentes, juntamente com a definição do Car
objeto.
Sem injeção de dependência (DI):
class Car{
private Wheel wh = new NepaliRubberWheel();
private Battery bt = new ExcideBattery();
//The rest
}
Aqui, o Car
objeto é responsável por criar os objetos dependentes.
E se quisermos mudar o tipo de seu objeto dependente - digamos Wheel
- após as NepaliRubberWheel()
perfurações iniciais ? Precisamos recriar o objeto Car com sua nova dependência ChineseRubberWheel()
, mas apenas o Car
fabricante pode fazer isso.
Então o que isso Dependency Injection
faz por nós ...?
Ao usar a injeção de dependência, os objetos recebem suas dependências no tempo de execução, em vez do tempo de compilação (tempo de fabricação do carro) . Para que agora possamos mudar o Wheel
que quisermos. Aqui, o dependency
( wheel
) pode ser injetado Car
no tempo de execução.
Depois de usar a injeção de dependência:
Aqui, estamos injetando as dependências (roda e bateria) em tempo de execução. Daí o termo: Injeção de Dependência.
class Car{
private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime
private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime
Car(Wheel wh,Battery bt) {
this.wh = wh;
this.bt = bt;
}
//Or we can have setters
void setWheel(Wheel wh) {
this.wh = wh;
}
}
new
um pneu? Eu não. Tudo o que tenho a fazer é comprar (injetar via param) deles, instalar e wah-lah! Portanto, voltando à programação, digamos que um projeto C # precise usar uma biblioteca / classe existente, há duas maneiras de executar / depurar, com uma referência de adição a todo o projeto
new
opção 2 e a passa como parâmetro. Pode não ser preciso, mas simples e estúpido, fácil de entender.
Injeção de Dependência é uma prática em que os objetos são projetados de maneira a receber instâncias dos objetos de outras partes do código, em vez de construí-los internamente. Isso significa que qualquer objeto que implemente a interface exigida pelo objeto pode ser substituído sem alterar o código, o que simplifica o teste e melhora a dissociação.
Por exemplo, considere estas classes:
public class PersonService {
public void addManager( Person employee, Person newManager ) { ... }
public void removeManager( Person employee, Person oldManager ) { ... }
public Group getGroupByManager( Person manager ) { ... }
}
public class GroupMembershipService() {
public void addPersonToGroup( Person person, Group group ) { ... }
public void removePersonFromGroup( Person person, Group group ) { ... }
}
Neste exemplo, a implementação de PersonService::addManager
e PersonService::removeManager
precisaria de uma instância do GroupMembershipService
para executar seu trabalho. Sem injeção de dependência, a maneira tradicional de fazer isso seria instanciar um novo GroupMembershipService
no construtor PersonService
e usar esse atributo de instância em ambas as funções. No entanto, se o construtor de GroupMembershipService
tem várias coisas que exige, ou pior ainda, existem alguns "setters" de inicialização que precisam ser chamados no GroupMembershipService
, o código cresce rapidamente, e o PersonService
agora depende não apenas do GroupMembershipService
mas também de tudo o mais que GroupMembershipService
depende de. Além disso, o vínculo GroupMembershipService
é codificado no código, o PersonService
que significa que você não pode "enganar" umGroupMembershipService
para fins de teste ou para usar um padrão de estratégia em diferentes partes do seu aplicativo.
Com a Injeção de Dependência, em vez de instanciar o GroupMembershipService
seu PersonService
, você deve passá-lo ao PersonService
construtor ou adicionar uma Propriedade (getter e setter) para definir uma instância local. Isso significa que você PersonService
não precisa mais se preocupar em como criar um GroupMembershipService
, apenas aceita os dados e trabalha com eles. Isso também significa que qualquer coisa que seja uma subclasse GroupMembershipService
ou implemente a GroupMembershipService
interface pode ser "injetada" no PersonService
e PersonService
não precisa saber sobre a alteração.
A resposta aceita é boa - mas eu gostaria de acrescentar que o DI é muito parecido com o clássico de evitar constantes codificadas no código.
Quando você usa alguma constante como o nome de um banco de dados, você a move rapidamente do interior do código para algum arquivo de configuração e passa uma variável que contém esse valor para o local em que é necessário. O motivo para fazer isso é que essas constantes geralmente mudam com mais frequência que o restante do código. Por exemplo, se você deseja testar o código em um banco de dados de teste.
O DI é análogo a isso no mundo da programação orientada a objetos. Os valores lá, em vez de literais constantes, são objetos inteiros - mas o motivo para mover o código que os cria a partir do código de classe é semelhante - os objetos mudam com mais frequência do que o código que os utiliza. Um caso importante em que essa mudança é necessária são os testes.
Vamos tentar um exemplo simples com as classes Car e Engine , qualquer carro precisa de um motor para ir a qualquer lugar, pelo menos por enquanto. Então, abaixo, como o código será exibido sem injeção de dependência.
public class Car
{
public Car()
{
GasEngine engine = new GasEngine();
engine.Start();
}
}
public class GasEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
E para instanciar a classe Car, usaremos o próximo código:
Car car = new Car();
O problema com este código que acoplamos firmemente ao GasEngine e, se decidirmos alterá-lo para o ElectricityEngine, precisaremos reescrever a classe Car. E quanto maior o aplicativo, mais problemas e dores de cabeça teremos para adicionar e usar um novo tipo de mecanismo.
Em outras palavras, com essa abordagem, nossa classe Car de alto nível depende da classe GasEngine de nível inferior, que viola o Princípio de Inversão de Dependência (DIP) do SOLID. O DIP sugere que devemos depender de abstrações, não de classes concretas. Então, para satisfazer isso, apresentamos a interface IEngine e reescrevemos o código como abaixo:
public interface IEngine
{
void Start();
}
public class GasEngine : IEngine
{
public void Start()
{
Console.WriteLine("I use gas as my fuel!");
}
}
public class ElectricityEngine : IEngine
{
public void Start()
{
Console.WriteLine("I am electrocar");
}
}
public class Car
{
private readonly IEngine _engine;
public Car(IEngine engine)
{
_engine = engine;
}
public void Run()
{
_engine.Start();
}
}
Agora nossa classe Car depende apenas da interface do IEngine, não de uma implementação específica do mecanismo. Agora, o único truque é como criamos uma instância do carro e fornecemos uma classe de mecanismo concreta real, como GasEngine ou ElectricityEngine. É aí que entra a injeção de dependência .
Car gasCar = new Car(new GasEngine());
gasCar.Run();
Car electroCar = new Car(new ElectricityEngine());
electroCar.Run();
Aqui basicamente injetamos (passamos) nossa dependência (instância do mecanismo) para o construtor Car. Portanto, agora nossas classes têm acoplamentos frouxos entre objetos e suas dependências, e podemos facilmente adicionar novos tipos de motores sem alterar a classe Car.
O principal benefício da Injeção de Dependência é que as classes são mais fracamente acopladas, porque não possuem dependências codificadas. Isso segue o Princípio de Inversão de Dependência, mencionado acima. Em vez de fazer referência a implementações específicas, as classes solicitam abstrações (geralmente interfaces ) que são fornecidas quando a classe é construída.
Portanto, no final, a injeção de dependência é apenas uma técnica para obter um acoplamento flexível entre objetos e suas dependências. Em vez de instanciar diretamente dependências que a classe precisa para executar suas ações, as dependências são fornecidas à classe (na maioria das vezes) por injeção de construtor.
Além disso, quando temos muitas dependências, é uma prática muito boa usar contêineres de Inversão de Controle (IoC), que podemos dizer quais interfaces devem ser mapeadas para quais implementações concretas para todas as nossas dependências e podemos resolver essas dependências para nós quando ele constrói nosso objeto. Por exemplo, podemos especificar no mapeamento do contêiner IoC que a dependência do IEngine deve ser mapeada para a classe GasEngine e, quando solicitarmos ao contêiner IoC uma instância da nossa classe Car , ele construirá automaticamente nossa classe Car com uma dependência GasEngine Transmitido.
ATUALIZAÇÃO: assisti recentemente a um curso sobre EF Core de Julie Lerman e também gostei de sua curta definição sobre DI.
A injeção de dependência é um padrão para permitir que seu aplicativo injete objetos dinamicamente nas classes que precisam deles, sem forçar essas classes a serem responsáveis por esses objetos. Ele permite que seu código seja mais livremente acoplado, e o Entity Framework Core se conecta a esse mesmo sistema de serviços.
Vamos imaginar que você quer pescar:
Sem injeção de dependência, você precisa cuidar de tudo sozinho. Você precisa encontrar um barco, comprar uma vara de pescar, procurar iscas etc. É possível, é claro, mas isso coloca muita responsabilidade em você. Em termos de software, isso significa que você precisa executar uma pesquisa para todas essas coisas.
Com a injeção de dependência, outra pessoa cuida de toda a preparação e disponibiliza o equipamento necessário. Você receberá ("seja injetado") o barco, a vara de pescar e a isca - tudo pronto para uso.
Esta é a explicação mais simples sobre Injeção de Dependência e Contêiner de Injeção de Dependência que eu já vi:
Injeção de dependência e recipientes de injeção de dependência são coisas diferentes:
Você não precisa de um contêiner para fazer a injeção de dependência. No entanto, um contêiner pode ajudá-lo.
"Injeção de dependência" não significa apenas o uso de construtores parametrizados e configuradores públicos?
O artigo de James Shore mostra os seguintes exemplos para comparação .
Construtor sem injeção de dependência:
public class Example { private DatabaseThingie myDatabase; public Example() { myDatabase = new DatabaseThingie(); } public void doStuff() { ... myDatabase.getData(); ... } }
Construtor com injeção de dependência:
public class Example { private DatabaseThingie myDatabase; public Example(DatabaseThingie useThisDatabaseInstead) { myDatabase = useThisDatabaseInstead; } public void doStuff() { ... myDatabase.getData(); ... } }
new DatabaseThingie()
não gerar uma instância válida do myDatabase.
Simplificar o conceito de Injeção de Dependência. Vamos dar um exemplo de botão para alternar (ligar / desligar) uma lâmpada.
O switch precisa saber com antecedência a qual bulbo estou conectado (dependência codificada). Assim,
Interruptor -> PermanentBulb // O interruptor está diretamente conectado à lâmpada permanente, não sendo possível testar facilmente
Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}
Apenas a chave sabe que preciso ligar / desligar a lâmpada que for passada para mim. Assim,
Alternar -> Bulb1 OU Bulb2 OU NightBulb (dependência injetada)
Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}
Modificando James Example para Switch e Bulb:
public class SwitchTest {
TestToggleBulb() {
MockBulb mockbulb = new MockBulb();
// MockBulb is a subclass of Bulb, so we can
// "inject" it here:
Switch switch = new Switch(mockBulb);
switch.ToggleBulb();
mockBulb.AssertToggleWasCalled();
}
}
public class Switch {
private Bulb myBulb;
public Switch() {
myBulb = new Bulb();
}
public Switch(Bulb useThisBulbInstead) {
myBulb = useThisBulbInstead;
}
public void ToggleBulb() {
...
myBulb.Toggle();
...
}
}`
O que é injeção de dependência (DI)?
Como já foi dito, o Injection de Dependência (DI) remove a responsabilidade da criação direta e do gerenciamento da vida útil de outras instâncias de objetos das quais nossa classe de interesse (classe de consumidor) depende (no sentido UML ). Em vez disso, essas instâncias são passadas para nossa classe de consumidor, normalmente como parâmetros do construtor ou por meio de configuradores de propriedades (o gerenciamento do objeto de dependência que instancia e passa para a classe de consumidor geralmente é realizado por uma Inversão de controle (IoC) contêiner , mas esse é outro tópico) .
DI, DIP e SOLID
Especificamente, no paradigma dos princípios SOLID de Robert C Martin de Design Orientado a Objetos , DI
é uma das possíveis implementações do Princípio de Inversão de Dependências (DIP) . O DIP é o D
do SOLID
mantra - outras implementações DIP incluem o Locator Service, e os padrões de Plugin.
O objetivo do DIP é dissociar dependências estreitas e concretas entre classes e, em vez disso, afrouxar o acoplamento por meio de uma abstração, que pode ser alcançada por meio de interface
, abstract class
oupure virtual class
, dependendo da linguagem e abordagem utilizada.
Sem o DIP, nosso código (eu chamei essa 'classe consumidora') está diretamente acoplado a uma dependência concreta e também costuma ser sobrecarregado com a responsabilidade de saber como obter e gerenciar uma instância dessa dependência, ou seja, conceitualmente:
"I need to create/use a Foo and invoke method `GetBar()`"
Considerando que, após a aplicação do DIP, o requisito é diminuído e a preocupação em obter e gerenciar a vida útil do Foo
dependência foi removida:
"I need to invoke something which offers `GetBar()`"
Por que usar DIP (e DI)?
A dissociação de dependências entre classes dessa maneira permite fácil substituição dessas classes de dependência por outras implementações que também atendem aos pré-requisitos da abstração (por exemplo, a dependência pode ser alternada com outra implementação da mesma interface). Além disso, como outros já mencionaram, possivelmente o motivo mais comum para desacoplar classes por meio do DIP é permitir que uma classe consumidora seja testada isoladamente, pois essas mesmas dependências agora podem ser stubadas e / ou zombadas.
Uma conseqüência do DI é que o gerenciamento da vida útil das instâncias do objeto de dependência não é mais controlado por uma classe consumidora, pois o objeto de dependência agora é passado para a classe consumidora (via injeção de construtor ou setter).
Isso pode ser visto de diferentes maneiras:
Create
na fábrica, conforme necessário, e descartá-las uma vez concluídas.Quando usar DI?
MyDepClass
thread é seguro - e se o tornarmos um singleton e injetarmos a mesma instância em todos os consumidores?)Exemplo
Aqui está uma implementação simples de C #. Dada a classe Consumidor abaixo:
public class MyLogger
{
public void LogRecord(string somethingToLog)
{
Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
}
}
Embora aparentemente inócuo, ele tem duas static
dependências de duas outras classes System.DateTime
eSystem.Console
, que não apenas limitam as opções de saída de log (o log no console será inútil se ninguém estiver assistindo), mas, pior ainda, é difícil testar automaticamente, dada a dependência de um relógio do sistema não determinístico.
No entanto, podemos aplicar DIP
a essa classe, abstraindo a preocupação do registro de data e hora como uma dependência e acoplando MyLogger
apenas a uma interface simples:
public interface IClock
{
DateTime Now { get; }
}
Também podemos diminuir a dependência Console
de uma abstração, como a TextWriter
. A injeção de dependência é normalmente implementada como constructor
injeção (passando uma abstração para uma dependência como parâmetro para o construtor de uma classe consumidora) ou Setter Injection
(passando a dependência por meio de um setXyz()
setter ou de uma propriedade .Net {set;}
definida). A injeção de construtor é preferida, pois isso garante que a classe estará em um estado correto após a construção e permite que os campos de dependência internos sejam marcados como readonly
(C #) ou final
(Java). Portanto, usando a injeção de construtor no exemplo acima, isso nos deixa com:
public class MyLogger : ILogger // Others will depend on our logger.
{
private readonly TextWriter _output;
private readonly IClock _clock;
// Dependencies are injected through the constructor
public MyLogger(TextWriter stream, IClock clock)
{
_output = stream;
_clock = clock;
}
public void LogRecord(string somethingToLog)
{
// We can now use our dependencies through the abstraction
// and without knowledge of the lifespans of the dependencies
_output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog);
}
}
(É Clock
necessário fornecer um concreto que, naturalmente, poderia reverter paraDateTime.Now
e as duas dependências precisam ser fornecidas por um contêiner de IoC via injeção de construtor)
Um teste de unidade automatizado pode ser construído, o que prova definitivamente que nosso criador de logs está funcionando corretamente, pois agora temos controle sobre as dependências - o tempo e podemos espionar a saída escrita:
[Test]
public void LoggingMustRecordAllInformationAndStampTheTime()
{
// Arrange
var mockClock = new Mock<IClock>();
mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45));
var fakeConsole = new StringWriter();
// Act
new MyLogger(fakeConsole, mockClock.Object)
.LogRecord("Foo");
// Assert
Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString());
}
Próximos passos
A injeção de dependência está invariavelmente associada a um contêiner de Inversão de Controle (IoC) , para injetar (fornecer) as instâncias de dependência concretas e gerenciar instâncias de vida útil. Durante o processo de configuração / inicialização, os IoC
contêineres permitem que seja definido o seguinte:
IBar
e retornar uma ConcreteBar
instância" )IDisposable
e assumem a responsabilidade de Disposing
dependências, de acordo com o gerenciamento da vida útil configurada.Normalmente, depois que os contêineres IoC são configurados / inicializados, eles operam perfeitamente em segundo plano, permitindo que o codificador se concentre no código em questão, em vez de se preocupar com dependências.
A chave do código compatível com DI é evitar o acoplamento estático de classes e não usar new () para a criação de dependências
Como no exemplo acima, a dissociação de dependências exige algum esforço de design e, para o desenvolvedor, é necessária uma mudança de paradigma para quebrar o hábito de new
dependências diretamente e, em vez disso, confiar no contêiner para gerenciar dependências.
Mas os benefícios são muitos, especialmente na capacidade de testar minuciosamente sua classe de interesse.
Nota : A criação / mapeamento / projeção (via new ..()
) de projeções POCO / POJO / DTOs de serialização / gráficos de entidades / JSON anônimas e outros - ou seja, classes ou registros "Somente dados" - usados ou retornados de métodos não são considerados dependências Sentido UML) e não sujeito a DI. Usar new
para projetar isso é ótimo.
O objetivo principal da injeção de dependência (DI) é manter o código-fonte do aplicativo limpo e estável :
Praticamente, todo padrão de design separa as preocupações para que mudanças futuras afetem os arquivos mínimos.
O domínio específico da DI é a delegação de configuração e inicialização de dependência.
Se você ocasionalmente trabalha fora de Java, lembre-se de como source
é frequentemente usado em muitas linguagens de script (Shell, Tcl etc.) ou mesmo import
em Python que são mal utilizadas para esse fim).
Considere um dependent.sh
script simples :
#!/bin/sh
# Dependent
touch "one.txt" "two.txt"
archive_files "one.txt" "two.txt"
O script é dependente: não será executado com êxito por conta própria (archive_files
não está definido).
Você define archive_files
no archive_files_zip.sh
script de implementação (usando zip
neste caso):
#!/bin/sh
# Dependency
function archive_files {
zip files.zip "$@"
}
Em vez de source
-ing script de implementação diretamente no dependente, você usa um injector.sh
"contêiner" que agrupa os dois "componentes":
#!/bin/sh
# Injector
source ./archive_files_zip.sh
source ./dependent.sh
A archive_files
dependência acaba de ser injetada no script dependente .
Você poderia ter injetado dependência que implementa archive_files
usando tar
or xz
.
Se o dependent.sh
script usasse dependências diretamente, a abordagem seria chamada de pesquisa de dependência (que é oposta à injeção de dependência ):
#!/bin/sh
# Dependent
# dependency look-up
source ./archive_files_zip.sh
touch "one.txt" "two.txt"
archive_files "one.txt" "two.txt"
Agora, o problema é que o "componente" dependente precisa executar a própria inicialização.
O código fonte do "componente" não é limpo nem estável pois todas as alterações na inicialização de dependências requerem nova liberação para o arquivo de código-fonte do "componente".
O DI não é tão amplamente enfatizado e popularizado quanto nas estruturas Java.
Mas é uma abordagem genérica para dividir as preocupações de:
O uso da configuração apenas com pesquisa de dependência não ajuda, pois o número de parâmetros de configuração pode mudar por dependência (por exemplo, novo tipo de autenticação), bem como o número de tipos de dependências suportados (por exemplo, novo tipo de banco de dados).
Todas as respostas acima são boas, meu objetivo é explicar o conceito de uma maneira simples, para que qualquer pessoa sem conhecimento de programação também possa entender o conceito.
A injeção de dependência é um dos padrões de design que nos ajudam a criar sistemas complexos de maneira mais simples.
Podemos ver uma ampla variedade de aplicações desse padrão em nossa vida cotidiana. Alguns exemplos são gravador, VCD, unidade de CD etc.
A imagem acima é uma imagem do gravador de rolo portátil, meados do século XX. Fonte .
A principal intenção de uma máquina gravadora é gravar ou reproduzir som.
Ao projetar um sistema, é necessário um rolo para gravar ou reproduzir som ou música. Existem duas possibilidades para projetar este sistema
Se usarmos o primeiro, precisamos abrir a máquina para trocar o rolo. se optarmos pelo segundo, que está colocando um gancho para o rolo, obteremos um benefício adicional de tocar qualquer música alterando o rolo. e também reduzindo a função apenas para reproduzir o que quer que esteja no rolo.
Como injeção de dependência sábia, é o processo de externalizar as dependências para focar apenas na funcionalidade específica do componente, de modo que componentes independentes possam ser acoplados para formar um sistema complexo.
Os principais benefícios que alcançamos usando a injeção de dependência.
Hoje em dia, esse conceito forma a base de estruturas bem conhecidas no mundo da programação. O Spring Angular etc são as estruturas de software conhecidas construídas no topo desse conceito
Injeção de dependência é um padrão usado para criar instâncias de objetos nos quais outros objetos confiam sem saber em tempo de compilação qual classe será usada para fornecer essa funcionalidade ou simplesmente a maneira de injetar propriedades em um objeto é chamada de injeção de dependência.
Exemplo para injeção de dependência
Anteriormente, estamos escrevendo código como este
Public MyClass{
DependentClass dependentObject
/*
At somewhere in our code we need to instantiate
the object with new operator inorder to use it or perform some method.
*/
dependentObject= new DependentClass();
dependentObject.someMethod();
}
Com a injeção de dependência, o injetor de dependência decola a instanciação para nós
Public MyClass{
/* Dependency injector will instantiate object*/
DependentClass dependentObject
/*
At somewhere in our code we perform some method.
The process of instantiation will be handled by the dependency injector
*/
dependentObject.someMethod();
}
Você também pode ler
Diferença entre Inversão de Controle e Injeção de Dependência
Injeção de Dependência (DI) significa dissociar os objetos que são dependentes um do outro. Digamos que o objeto A seja dependente do Objeto B, portanto a idéia é separar esses objetos um do outro. Não precisamos codificar o objeto usando uma nova palavra-chave, em vez de compartilhar dependências para objetos em tempo de execução, apesar do tempo de compilação. Se falamos sobre
Não precisamos codificar o objeto usando a nova palavra-chave, em vez de definir a dependência do bean no arquivo de configuração. O contêiner de mola será responsável por conectar todos.
O COI é um conceito geral e pode ser expresso de diversas maneiras e a Injeção de Dependência é um exemplo concreto do COI.
O DI baseado em construtor é realizado quando o contêiner chama um construtor de classe com vários argumentos, cada um representando uma dependência de outra classe.
public class Triangle {
private String type;
public String getType(){
return type;
}
public Triangle(String type){ //constructor injection
this.type=type;
}
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
<constructor-arg value="20"/>
</bean>
O DI baseado em setter é realizado pelo contêiner que chama métodos setter em seus beans após a invocação de um construtor sem argumento ou método de fábrica estático sem argumento para instanciar seu bean.
public class Triangle{
private String type;
public String getType(){
return type;
}
public void setType(String type){ //setter injection
this.type = type;
}
}
<!-- setter injection -->
<bean id="triangle" class="com.test.dependencyInjection.Triangle">
<property name="type" value="equivialteral"/>
NOTA: É uma boa regra geral usar argumentos de construtor para dependências obrigatórias e setters para dependências opcionais. Observe que a anotação se usarmos anotação baseada em @Required em um setter pode ser usada para fazer setters como dependências necessárias.
A melhor analogia em que consigo pensar é no cirurgião e seus assistentes em uma sala de operações, onde o cirurgião é a pessoa principal e seu assistente que fornece os vários componentes cirúrgicos quando ele precisa para que o cirurgião possa se concentrar naquele coisa que ele faz melhor (cirurgia). Sem o assistente, o cirurgião precisa obter os componentes sempre que precisar.
DI, para abreviar, é uma técnica para remover uma responsabilidade adicional comum (carga) dos componentes para buscar os componentes dependentes, fornecendo-os a eles.
O DI aproxima você do princípio de responsabilidade única (SR), como o surgeon who can concentrate on surgery
.
Quando usar o DI: eu recomendaria usá-lo em quase todos os projetos de produção (pequenos / grandes), especialmente em ambientes de negócios sempre em mudança :)
Motivo: como você deseja que seu código seja facilmente testável, zombável, etc., para que você possa testar rapidamente suas alterações e enviá-lo ao mercado. Além disso, por que você não faria isso quando houvesse muitas ferramentas / estruturas gratuitas impressionantes para ajudá-lo em sua jornada para uma base de código onde você tem mais controle.
Exemplo, temos 2 classes Client
e Service
. Client
usaráService
public class Service {
public void doSomeThingInService() {
// ...
}
}
Caminho 1)
public class Client {
public void doSomeThingInClient() {
Service service = new Service();
service.doSomeThingInService();
}
}
Caminho 2)
public class Client {
Service service = new Service();
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Caminho 3)
public class Client {
Service service;
public Client() {
service = new Service();
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
1) 2) 3) Usando
Client client = new Client();
client.doSomeThingInService();
Vantagens
Desvantagens
Client
classe deService
construtor, precisamos alterar o código em todos os lugaresService
objetoManeira 1) Injeção de construtor
public class Client {
Service service;
Client(Service service) {
this.service = service;
}
// Example Client has 2 dependency
// Client(Service service, IDatabas database) {
// this.service = service;
// this.database = database;
// }
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Usando
Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();
Maneira 2) Injeção do setter
public class Client {
Service service;
public void setService(Service service) {
this.service = service;
}
public void doSomeThingInClient() {
service.doSomeThingInService();
}
}
Usando
Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();
Caminho 3) Injeção de interface
Verifica https://en.wikipedia.org/wiki/Dependency_injection
===
Agora, esse código já está sendo seguido Dependency Injection
e é mais fácil para a Client
classe de teste .
No entanto, ainda usamos new Service()
muito tempo e não é bom quando o Service
construtor de alterações . Para evitá-lo, podemos usar o injetor DI como
1) Manual simplesInjector
public class Injector {
public static Service provideService(){
return new Service();
}
public static IDatabase provideDatatBase(){
return new SqliteDatabase();
}
public static ObjectA provideObjectA(){
return new ObjectA(provideService(...));
}
}
Usando
Service service = Injector.provideService();
2) Usar biblioteca: para Android dagger2
Vantagens
Service
, você só precisa alterá-lo na classe InjectorConstructor Injection
, quando olhar para o construtor de Client
, verá quantas dependências de Client
classeDesvantagens
Constructor Injection
, o Service
objeto será criado quando Client
criado. Às vezes, usamos a função na Client
classe sem o uso, Service
portanto, o Service
desperdício é desperdiçado.https://en.wikipedia.org/wiki/Dependency_injection
Uma dependência é um objeto que pode ser usado (
Service
)
Uma injeção é a passagem de uma dependência (Service
) para um objeto dependente (Client
) que a usaria
Isso significa que os objetos devem ter apenas quantas dependências forem necessárias para realizar seu trabalho e as dependências devem ser poucas. Além disso, as dependências de um objeto devem estar em interfaces e não em objetos "concretos", quando possível. (Um objeto concreto é qualquer objeto criado com a palavra-chave new.) O acoplamento flexível promove maior reutilização, manutenção mais fácil e permite que você forneça facilmente objetos "simulados" em vez de serviços caros.
A "Injeção de Dependência" (DI) também é conhecida como "Inversão de Controle" (IoC), pode ser usada como uma técnica para incentivar esse acoplamento solto.
Existem duas abordagens principais para implementar a DI:
É a técnica de passar dependências de objetos para seu construtor.
Observe que o construtor aceita uma interface e não um objeto concreto. Além disso, observe que uma exceção será lançada se o parâmetro orderDao for nulo. Isso enfatiza a importância de receber uma dependência válida. Injeção de construtor é, na minha opinião, o mecanismo preferido para atribuir a um objeto suas dependências. É claro para o desenvolvedor, enquanto invoca o objeto, quais dependências precisam ser dadas ao objeto "Pessoa" para uma execução adequada.
Mas considere o exemplo a seguir ... Suponha que você tenha uma classe com dez métodos que não têm dependências, mas você está adicionando um novo método que depende do IDAO. Você pode alterar o construtor para usar a Injeção de construtor, mas isso pode forçá-lo a alterar todas as chamadas de construtor em todo o lugar. Como alternativa, você pode simplesmente adicionar um novo construtor que aceite a dependência, mas como um desenvolvedor sabe facilmente quando usar um construtor sobre o outro. Por fim, se a dependência é muito cara de criar, por que deveria ser criada e transmitida ao construtor quando só pode ser usada raramente? “Injeção de incubadora” é outra técnica de DI que pode ser usada em situações como essa.
A injeção do setter não força dependências a serem passadas para o construtor. Em vez disso, as dependências são definidas nas propriedades públicas expostas pelo objeto em necessidade. Como implicado anteriormente, os principais motivadores para fazer isso incluem:
Aqui está o exemplo de como seria o código acima:
public class Person {
public Person() {}
public IDAO Address {
set { addressdao = value; }
get {
if (addressdao == null)
throw new MemberAccessException("addressdao" +
" has not been initialized");
return addressdao;
}
}
public Address GetAddress() {
// ... code that uses the addressdao object
// to fetch address details from the datasource ...
}
// Should not be called directly;
// use the public property instead
private IDAO addressdao;
Eu acho que desde que todos tenham escrito para DI, deixe-me fazer algumas perguntas ..
Isso se baseia na resposta que @Adam N postou.
Por que o PersonService não precisa mais se preocupar com o GroupMembershipService? Você acabou de mencionar que GroupMembership possui várias coisas (objetos / propriedades) das quais depende. Se o GMService fosse necessário no PService, você o teria como propriedade. Você pode zombar disso, independentemente de você ter injetado ou não. A única vez que eu gostaria que fosse injetado seria se o GMService tivesse classes filho mais específicas, que você não saberia até o tempo de execução. Então você deseja injetar a subclasse. Ou se você quiser usá-lo como singleton ou protótipo. Para ser sincero, o arquivo de configuração tem tudo codificado até a subclasse de um tipo (interface) que ele injeta durante o tempo de compilação.
EDITAR
Um bom comentário de Jose Maria Arranz em DI
O DI aumenta a coesão ao remover qualquer necessidade de determinar a direção da dependência e escrever qualquer código de cola.
Falso. A direção das dependências está no formato XML ou como anotações, suas dependências são gravadas como código XML e anotações. XML e anotações SÃO código fonte.
O DI reduz o acoplamento, tornando todos os seus componentes modulares (ou seja, substituíveis) e tendo interfaces bem definidas entre si.
Falso. Você não precisa de uma estrutura DI para criar um código modular baseado em interfaces.
Sobre substituíveis: com um arquivo .properties muito simples e Class.forName, você pode definir quais classes podem mudar. Se QUALQUER classe do seu código puder ser alterada, Java não é para você, use uma linguagem de script. A propósito: as anotações não podem ser alteradas sem a recompilação.
Na minha opinião, há uma única razão para as estruturas DI: redução da placa da caldeira. Com um sistema de fábrica bem-feito, você pode fazer o mesmo, mais controlado e mais previsível que sua estrutura DI preferida, as estruturas DI prometem redução de código (XML e anotações também são código fonte). O problema é que a redução da placa da caldeira é real apenas em casos muito simples (uma instância por classe e semelhante), às vezes no mundo real escolher o objeto de serviço apropriado não é tão fácil quanto mapear uma classe para um objeto singleton.
As respostas populares são inúteis, porque definem a injeção de dependência de uma maneira que não é útil. Vamos concordar que por "dependência" queremos dizer algum outro objeto preexistente que nosso objeto X precisa. Mas não dizemos que estamos fazendo "injeção de dependência" quando dizemos
$foo = Foo->new($bar);
Apenas chamamos esses parâmetros de passagem para o construtor. Fazemos isso regularmente desde que os construtores foram inventados.
"Injeção de dependência" é considerado um tipo de "inversão de controle", o que significa que alguma lógica é retirada do chamador. Esse não é o caso quando o chamador passa os parâmetros, portanto, se isso fosse DI, DI não implicaria inversão de controle.
DI significa que existe um nível intermediário entre o responsável pela chamada e o construtor que gerencia dependências. Um Makefile é um exemplo simples de injeção de dependência. O "chamador" é a pessoa que digita "make bar" na linha de comando e o "construtor" é o compilador. O Makefile especifica que a barra depende de foo e faz uma
gcc -c foo.cpp; gcc -c bar.cpp
antes de fazer um
gcc foo.o bar.o -o bar
A pessoa digitando "make bar" não precisa saber que a barra depende de foo. A dependência foi injetada entre "make bar" e gcc.
O principal objetivo do nível intermediário não é apenas passar as dependências para o construtor, mas listar todas as dependências em apenas um local e ocultá-las do codificador (não fazer com que o codificador as forneça).
Geralmente, o nível intermediário fornece fábricas para os objetos construídos, que devem fornecer uma função que cada tipo de objeto solicitado deve satisfazer. Isso porque, ao ter um nível intermediário que oculta os detalhes da construção, você já incorreu na penalidade de abstração imposta pelas fábricas, para que você também possa usá-las.
Injeção de Dependência significa uma maneira (na verdade de qualquer maneira ) de uma parte do código (por exemplo, uma classe) ter acesso a dependências (outras partes do código, por exemplo, outras classes, depende) de uma maneira modular sem que elas sejam codificadas (portanto eles podem ser alterados ou substituídos livremente ou até carregados em outro momento, conforme necessário)
(e ps, sim, tornou-se um nome exagerado em 25 $ para um conceito bastante simples) , meus .25
centavos
Sei que já existem muitas respostas, mas achei muito útil: http://tutorials.jenkov.com/dependency-injection/index.html
public class MyDao {
protected DataSource dataSource = new DataSourceImpl(
"driver", "url", "user", "password");
//data access methods...
public Person readPerson(int primaryKey) {...}
}
public class MyDao {
protected DataSource dataSource = null;
public MyDao(String driver, String url, String user, String password) {
this.dataSource = new DataSourceImpl(driver, url, user, password);
}
//data access methods...
public Person readPerson(int primaryKey) {...}
}
Observe como a DataSourceImpl
instanciação é movida para um construtor. O construtor usa quatro parâmetros, que são os quatro valores necessários para o DataSourceImpl
. Embora a MyDao
classe ainda dependa desses quatro valores, ela não satisfaz mais essas dependências. Eles são fornecidos por qualquer classe que esteja criando uma MyDao
instância.
A injeção de dependência é uma solução possível para o que geralmente poderia ser chamado de requisito de "Ofuscação da dependência". Ocultação de dependência é um método de tirar a natureza "óbvia" do processo de fornecer uma dependência a uma classe que a exige e, portanto, ofuscar, de alguma forma, o fornecimento da referida dependência à referida classe. Isto não é necessariamente uma coisa ruim. De fato, ofuscando a maneira pela qual uma dependência é fornecida a uma classe, algo fora da classe é responsável por criar a dependência, o que significa que, em vários cenários, uma implementação diferente da dependência pode ser fornecida à classe sem fazer alterações. para a aula. Isso é ótimo para alternar entre os modos de produção e teste (por exemplo, usando uma dependência de serviço 'falsa').
Infelizmente, a parte ruim é que algumas pessoas assumiram que você precisa de uma estrutura especializada para ofuscar a dependência e que você é de algum modo um programador 'menor' se optar por não usar uma estrutura específica para isso. Outro mito extremamente perturbador, acreditado por muitos, é que a injeção de dependência é a única maneira de obter a ofuscação da dependência. Isso é demonstrável, histórica e obviamente 100% errado, mas você terá problemas para convencer algumas pessoas de que existem alternativas à injeção de dependência para seus requisitos de ofuscação de dependência.
Os programadores entendem o requisito de ofuscação de dependência há anos e muitas soluções alternativas evoluíram antes e depois da concepção da injeção de dependência. Existem padrões de fábrica, mas também existem muitas opções usando o ThreadLocal onde nenhuma injeção é necessária em uma instância específica - a dependência é efetivamente injetada no encadeamento, o que tem o benefício de disponibilizar o objeto (por meio de métodos getter estáticos convenientes). qualquerclasse que exige isso sem ter que adicionar anotações às classes que exigem isso e configurar 'cola' XML complexa para que isso aconteça. Quando suas dependências são necessárias para persistência (JPA / JDO ou o que for), permite que você obtenha 'persistência tranparente' muito mais fácil e com classes de modelo de domínio e modelo de negócio compostas apenas por POJOs (ou seja, nenhuma estrutura específica / bloqueada em anotações).
Do livro, ' Desenvolvedor Java bem fundamentado: técnicas vitais de Java 7 e programação poliglota
A DI é uma forma específica de IoC, na qual o processo de localização de suas dependências está fora do controle direto do código em execução no momento.
Antes de ir para a descrição técnica, visualize-a primeiro com um exemplo da vida real, porque você encontrará muitas coisas técnicas para aprender a injeção de dependência, mas o tempo máximo que pessoas como eu não conseguem entender o conceito principal.
Na primeira foto, suponha que você tenha uma fábrica de automóveis com muitas unidades. Um carro é realmente construído na unidade de montagem, mas precisa de motor , assentos e rodas . Portanto , a unidade de montagem depende dessas unidades e são dependências da fábrica.
Você pode sentir que agora é muito complicado manter todas as tarefas nesta fábrica porque, junto com a tarefa principal (Montar carro na unidade de montagem), você também precisa se concentrar em outras unidades . Agora, é muito caro manter e o prédio da fábrica é enorme, por isso é preciso muito dinheiro para alugar.
Agora, olhe para a segunda foto. Se você encontrar algumas empresas fornecedoras que fornecerão a você roda , assento e motor mais baratos que o custo de autoprodução, agora você não precisa instalá-las em sua fábrica. Agora você pode alugar um prédio menor apenas para sua unidade de montagem, o que diminuirá sua tarefa de manutenção e reduzirá o custo extra de aluguel. Agora você também pode se concentrar apenas na sua tarefa principal (montagem do carro).
Agora podemos dizer que todas as dependências para montar um carro são injetadas na fábrica pelos fornecedores . É um exemplo de injeção de dependência (DI) da vida real .
Agora, na palavra técnica, injeção de dependência é uma técnica pela qual um objeto (ou método estático) fornece as dependências de outro objeto. Portanto, transferir a tarefa de criar o objeto para outra pessoa e usar diretamente a dependência é chamado de injeção de dependência.
Isso irá ajudá-lo agora a aprender DI com alguma palavra técnica. Isso mostrará quando usar DI e quando não deve .
do Book Apress.Spring.Persistence.with.Hibernate.Oct.2010
O objetivo da injeção de dependência é dissociar o trabalho de resolver componentes de software externos da lógica de negócios do aplicativo. Sem injeção de dependência, os detalhes de como um componente acessa os serviços necessários podem ficar confusos com o código do componente. Isso não apenas aumenta o potencial de erros, adiciona inchaço ao código e amplia as complexidades de manutenção; ele une os componentes mais estreitamente, dificultando a modificação de dependências ao refatorar ou testar.
A Injeção de Dependência (DI) é uma das Design Patterns, que usa o recurso básico do OOP - o relacionamento em um objeto com outro objeto. Enquanto a herança herda um objeto para tornar mais complexo e específico outro objeto, o relacionamento ou a associação simplesmente cria um ponteiro para outro objeto de um objeto usando o atributo O poder do DI está em combinação com outros recursos do OOP, assim como as interfaces e o código oculto. Suponha que tenhamos um cliente (assinante) na biblioteca, que pode emprestar apenas um livro por simplicidade.
Interface do livro:
package com.deepam.hidden;
public interface BookInterface {
public BookInterface setHeight(int height);
public BookInterface setPages(int pages);
public int getHeight();
public int getPages();
public String toString();
}
Em seguida, podemos ter muitos tipos de livros; um dos tipos é ficção:
package com.deepam.hidden;
public class FictionBook implements BookInterface {
int height = 0; // height in cm
int pages = 0; // number of pages
/** constructor */
public FictionBook() {
// TODO Auto-generated constructor stub
}
@Override
public FictionBook setHeight(int height) {
this.height = height;
return this;
}
@Override
public FictionBook setPages(int pages) {
this.pages = pages;
return this;
}
@Override
public int getHeight() {
// TODO Auto-generated method stub
return height;
}
@Override
public int getPages() {
// TODO Auto-generated method stub
return pages;
}
@Override
public String toString(){
return ("height: " + height + ", " + "pages: " + pages);
}
}
Agora, o assinante pode ter associação ao livro:
package com.deepam.hidden;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Subscriber {
BookInterface book;
/** constructor*/
public Subscriber() {
// TODO Auto-generated constructor stub
}
// injection I
public void setBook(BookInterface book) {
this.book = book;
}
// injection II
public BookInterface setBook(String bookName) {
try {
Class<?> cl = Class.forName(bookName);
Constructor<?> constructor = cl.getConstructor(); // use it for parameters in constructor
BookInterface book = (BookInterface) constructor.newInstance();
//book = (BookInterface) Class.forName(bookName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return book;
}
public BookInterface getBook() {
return book;
}
public static void main(String[] args) {
}
}
Todas as três classes podem ser ocultadas para sua própria implementação. Agora podemos usar este código para DI:
package com.deepam.implement;
import com.deepam.hidden.Subscriber;
import com.deepam.hidden.FictionBook;
public class CallHiddenImplBook {
public CallHiddenImplBook() {
// TODO Auto-generated constructor stub
}
public void doIt() {
Subscriber ab = new Subscriber();
// injection I
FictionBook bookI = new FictionBook();
bookI.setHeight(30); // cm
bookI.setPages(250);
ab.setBook(bookI); // inject
System.out.println("injection I " + ab.getBook().toString());
// injection II
FictionBook bookII = ((FictionBook) ab.setBook("com.deepam.hidden.FictionBook")).setHeight(5).setPages(108); // inject and set
System.out.println("injection II " + ab.getBook().toString());
}
public static void main(String[] args) {
CallHiddenImplBook kh = new CallHiddenImplBook();
kh.doIt();
}
}
Existem várias maneiras diferentes de usar a injeção de dependência. É possível combiná-lo com Singleton, etc., mas ainda é básico, apenas a associação é realizada através da criação de atributo do tipo de objeto dentro de outro objeto. A utilidade é única e somente característica, esse código, que devemos escrever repetidamente, está sempre preparado e pronto para seguir adiante. É por isso que o DI está tão intimamente ligado à Inversion of Control (IoC), o que significa que nosso programa passa a controlar outro módulo em execução, que injeta beans no nosso código. (Cada objeto que pode ser injetado pode ser assinado ou considerado como um Bean.) Por exemplo, no Spring, isso é feito através da criação e inicialização ApplicationContextcontainer, o que funciona para nós. Simplesmente em nosso código, criamos o Contexto e chamamos a inicialização dos beans. Nesse momento, a injeção foi feita automaticamente.
Injeção de Dependência para crianças de 5 anos.
Quando você tira as coisas da geladeira, pode causar problemas. Você pode deixar a porta aberta, pode conseguir algo que mamãe ou papai não querem que você tenha. Você pode até estar procurando por algo que nem sequer temos ou que expirou.
O que você deve fazer é declarar uma necessidade: "Preciso beber alguma coisa no almoço" e, em seguida, garantiremos que você tenha alguma coisa quando se sentar para comer.
De Christoffer Noring, o livro de Pablo Deeleman "Learning Angular - Second Edition":
"À medida que nossos aplicativos crescem e evoluem, cada uma de nossas entidades de código exigirá internamente instâncias de outros objetos , mais conhecidos como dependências no mundo da engenharia de software. A ação de passar essas dependências para o cliente dependente é conhecida como injeção , e implica também a participação de outra entidade de código, chamado de injector . o injector irá assumir a responsabilidade por instanciar e bootstrapping o necessário dependênciasentão eles estão prontos para uso a partir do momento em que são injetados com sucesso no cliente. Isso é muito importante, pois o cliente não sabe nada sobre como instanciar suas próprias dependências e só conhece a interface. que implementa para usá-las. "
De: Anton Moiseev. livro "Desenvolvimento Angular com Texto Datilografado, Segunda Edição".
"Em resumo, o DI ajuda a escrever o código de uma maneira pouco acoplada e torna seu código mais testável e reutilizável ."
Em palavras simples, a injeção de dependência (DI) é a maneira de remover dependências ou acoplamentos estreitos entre objetos diferentes. A injeção de dependência oferece um comportamento coeso para cada objeto.
DI é a implementação do diretor do COI da Spring que diz "Não ligue para nós, ligaremos para você". O uso do programador de injeção de dependência não precisa criar objetos usando a nova palavra-chave.
Os objetos são carregados uma vez no contêiner Spring e, em seguida, os reutilizamos sempre que precisamos, buscando esses objetos no contêiner Spring usando o método getBean (String beanName).
A injeção de dependência é o cerne do conceito relacionado ao Spring Framework. Ao criar o quadro de qualquer projeto, a primavera pode desempenhar um papel vital, e aqui a injeção de dependência entra no jarro.
Na verdade, suponha que em java você tenha criado duas classes diferentes como classe A e classe B, e qualquer que seja a função disponível na classe B que você deseja usar na classe A, portanto, nesse momento, a injeção de dependência pode ser usada. onde você pode criar objetos de uma classe em outra, da mesma maneira que você pode injetar uma classe inteira em outra classe para torná-lo acessível. dessa maneira, a dependência pode ser superada.
A INJEÇÃO POR DEPENDÊNCIA SIMPLESMENTE ESTÁ COLOCANDO DUAS AULAS E AO MESMO TEMPO MANTENDO-AS SEPARADAS.