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:Problema : Se
myObject
envolver tarefas complexas, como acesso ao disco ou à rede, é difícil realizar testes de unidadeSomeClass()
. Os programadores precisam zombarmyObject
e podem interceptar a chamada de fábrica.Solução alternativa :
myObject
como um argumento para o construtormyObject
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.
fonte
A melhor definição que encontrei até agora é uma de James Shore :
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.
fonte
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 doCar
objeto.Sem injeção de dependência (DI):
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 asNepaliRubberWheel()
perfurações iniciais ? Precisamos recriar o objeto Car com sua nova dependênciaChineseRubberWheel()
, mas apenas oCar
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, odependency
(wheel
) pode ser injetadoCar
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.
Fonte: Entendendo a injeção de dependência
fonte
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 projetonew
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:
Neste exemplo, a implementação de
PersonService::addManager
ePersonService::removeManager
precisaria de uma instância doGroupMembershipService
para executar seu trabalho. Sem injeção de dependência, a maneira tradicional de fazer isso seria instanciar um novoGroupMembershipService
no construtorPersonService
e usar esse atributo de instância em ambas as funções. No entanto, se o construtor deGroupMembershipService
tem várias coisas que exige, ou pior ainda, existem alguns "setters" de inicialização que precisam ser chamados noGroupMembershipService
, o código cresce rapidamente, e oPersonService
agora depende não apenas doGroupMembershipService
mas também de tudo o mais queGroupMembershipService
depende de. Além disso, o vínculoGroupMembershipService
é codificado no código, oPersonService
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
seuPersonService
, você deve passá-lo aoPersonService
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 umGroupMembershipService
, apenas aceita os dados e trabalha com eles. Isso também significa que qualquer coisa que seja uma subclasseGroupMembershipService
ou implemente aGroupMembershipService
interface pode ser "injetada" noPersonService
ePersonService
não precisa saber sobre a alteração.fonte
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.
fonte
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.
E para instanciar a classe Car, usaremos o próximo código:
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:
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 .
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.
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.
fonte
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.
fonte
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:
Sem injeção de dependência
Com injeção de dependência
Usando um contêiner de injeção de dependência
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.
fonte
"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 .
fonte
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.
Sem injeção de dependência
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
Com injeção de dependência
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)
Modificando James Example para Switch e Bulb:
fonte
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 é oD
doSOLID
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:
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: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:
Embora aparentemente inócuo, ele tem duas
static
dependências de duas outras classesSystem.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 acoplandoMyLogger
apenas a uma interface simples:Também podemos diminuir a dependência
Console
de uma abstração, como aTextWriter
. A injeção de dependência é normalmente implementada comoconstructor
injeção (passando uma abstração para uma dependência como parâmetro para o construtor de uma classe consumidora) ouSetter Injection
(passando a dependência por meio de umsetXyz()
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 comoreadonly
(C #) oufinal
(Java). Portanto, usando a injeção de construtor no exemplo acima, isso nos deixa com:(É
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:
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 umaConcreteBar
instância" )IDisposable
e assumem a responsabilidade deDisposing
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.
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. Usarnew
para projetar isso é ótimo.fonte
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.
Exemplo: DI com script de shell
Se você ocasionalmente trabalha fora de Java, lembre-se de como
source
é frequentemente usado em muitas linguagens de script (Shell, Tcl etc.) ou mesmoimport
em Python que são mal utilizadas para esse fim).Considere um
dependent.sh
script simples :O script é dependente: não será executado com êxito por conta própria (
archive_files
não está definido).Você define
archive_files
noarchive_files_zip.sh
script de implementação (usandozip
neste caso):Em vez de
source
-ing script de implementação diretamente no dependente, você usa uminjector.sh
"contêiner" que agrupa os dois "componentes":A
archive_files
dependência acaba de ser injetada no script dependente .Você poderia ter injetado dependência que implementa
archive_files
usandotar
orxz
.Exemplo: removendo DI
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 ):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".
Últimas palavras
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).
fonte
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
Com a injeção de dependência, o injetor de dependência decola a instanciação para nós
Você também pode ler
Diferença entre Inversão de Controle e Injeção de Dependência
fonte
O que é 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
Como a injeção de dependência funciona na primavera:
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.
Inversão de Controle (COI)
O COI é um conceito geral e pode ser expresso de diversas maneiras e a Injeção de Dependência é um exemplo concreto do COI.
Dois tipos de injeção de dependência:
1. Injeção de dependência baseada em construtor:
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.
2. Injeção de dependência baseada em setter:
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.
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.
fonte
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.
fonte
Exemplo, temos 2 classes
Client
eService
.Client
usaráService
Sem injeção de dependência
Caminho 1)
Caminho 2)
Caminho 3)
1) 2) 3) Usando
Vantagens
Desvantagens
Client
classe deService
construtor, precisamos alterar o código em todos os lugaresService
objetoUsar injeção de dependência
Maneira 1) Injeção de construtor
Usando
Maneira 2) Injeção do setter
Usando
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 aClient
classe de teste .No entanto, ainda usamos
new Service()
muito tempo e não é bom quando oService
construtor de alterações . Para evitá-lo, podemos usar o injetor DI como1) Manual simples
Injector
Usando
2) Usar biblioteca: para Android dagger2
Vantagens
Service
, você só precisa alterá-lo na classe InjectorConstructor Injection
, quando olhar para o construtor deClient
, verá quantas dependências deClient
classeDesvantagens
Constructor Injection
, oService
objeto será criado quandoClient
criado. Às vezes, usamos a função naClient
classe sem o uso,Service
portanto, oService
desperdício é desperdiçado.Definição de Injeção de Dependência
https://en.wikipedia.org/wiki/Dependency_injection
fonte
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:
Injeção de construtor
É 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.
Injeção de Setter
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:
fonte
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.
fonte
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
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
antes de fazer um
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.
fonte
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
centavosfonte
Sei que já existem muitas respostas, mas achei muito útil: http://tutorials.jenkov.com/dependency-injection/index.html
Sem dependência:
Dependência:
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 oDataSourceImpl
. Embora aMyDao
classe ainda dependa desses quatro valores, ela não satisfaz mais essas dependências. Eles são fornecidos por qualquer classe que esteja criando umaMyDao
instância.fonte
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).
fonte
Do livro, ' Desenvolvedor Java bem fundamentado: técnicas vitais de Java 7 e programação poliglota
fonte
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 .
.
fonte
do Book Apress.Spring.Persistence.with.Hibernate.Oct.2010
fonte
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:
Em seguida, podemos ter muitos tipos de livros; um dos tipos é ficção:
Agora, o assinante pode ter associação ao livro:
Todas as três classes podem ser ocultadas para sua própria implementação. Agora podemos usar este código para DI:
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.
fonte
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.
fonte
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 ."
fonte
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).
fonte
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.
fonte