O que é injeção de dependência e inversão de controle no Spring Framework?

112

"Dependency Injection" e "Inversion of Control" são frequentemente mencionados como as principais vantagens de usar a estrutura Spring para desenvolver estruturas da Web

Alguém poderia explicar o que é em termos muito simples com um exemplo, se possível?

Chillax
fonte
possível duplicata de O que é inversão de controle?
Steve Chambers,
3
@SteveChambers não é duplicado, esta pergunta é feita em Springs Perspective. Essa questão é em geral prespectiva.
VdeX

Respostas:

233
  • O Spring ajuda na criação de aplicativos fracamente acoplados por causa da injeção de dependência .
  • No Spring, os objetos definem suas associações (dependências) e não se preocupam em como obterão essas dependências . É responsabilidade do Spring fornecer as dependências necessárias para a criação de objetos.

Por exemplo : suponha que temos um objeto Employeee ele depende do objeto Address. Nós definiríamos um bean correspondente a Employeeque definirá sua dependência do objeto Address.

Quando o Spring tenta criar um Employeeobjeto, ele verá que Employeetem uma dependência de Address, então ele primeiro criará o Addressobjeto (objeto dependente) e então o injetará no Employeeobjeto.

  • Inversão de controle ( IoC ) e injeção de dependência ( DI ) são usados ​​indistintamente. IoC é alcançado por meio de DI. DI é o processo de fornecer as dependências e IoC é o resultado final do DI. ( Observação: DI não é a única maneira de alcançar IoC. Existem outras maneiras também.)

  • Por DI, a responsabilidade de criar objetos é transferida do código do nosso aplicativo para o contêiner Spring; este fenômeno é denominado IoC.

  • A injeção de dependência pode ser feita por injeção de setter ou injeção de construtor.
Krishnakant Kadam
fonte
Discordo. não acho que seja uma explicação clara. Por que você não pode apenas instanciar "Address" dentro de "Employee" em vez de obter um framework para cretá-lo e injetá-lo? Um exemplo um pouco mais detalhado é necessário.
Boris de
2
@Boris Ninguém disse que você não pode instanciar seus próprios objetos. Mas o único objetivo da resposta era demonstrar como você pode conseguir o mesmo com o DI. Você pode ter DI e objetos instanciados pelo código do cliente. Isso ainda seria chamado de IOC, pelo menos parcialmente.
bogdan.rusu
Boris. Muito ciumento? Essa é a melhor resposta de todas.
Aniket Kapse
31

Vou escrever minha compreensão simples desses dois termos: (Para uma compreensão rápida, basta ler os exemplos)

  • Injeção de dependência (DI):
    injeção de dependência geralmente significa passar um objeto dependente como parâmetro para um método, em vez de fazer com que o método crie o objeto dependente .
    Na prática, isso significa que o método não depende diretamente de uma implementação específica; qualquer implementação que atenda aos requisitos pode ser passada como parâmetro.

    Com esta implementação de objetos define suas dependências. E a primavera o disponibiliza.
    Isso leva ao desenvolvimento de aplicativos fracamente acoplados.

    Exemplo Rápido: OBJETO EMPREGADO QUANDO CRIADO, CRIARÁ AUTOMATICAMENTE O OBJETO ENDEREÇO ​​(se o endereço for definido como dependência pelo objeto Funcionário) *.

  • Recipiente de Inversão de Controle (IoC):
    Esta é uma característica comum de frameworks. IoC gerencia objetos java
    - da instanciação à destruição através de sua BeanFactory.
    - Os componentes Java que são instanciados pelo contêiner IoC são chamados de beans, e o contêiner IoC gerencia o escopo de um bean, eventos de ciclo de vida e quaisquer recursos AOP para os quais ele foi configurado e codificado.

    QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

    Ao implementar a Inversão de Controle, um consumidor de software / objeto obtém mais controles / opções sobre o software / objetos, em vez de ser controlado ou ter menos opções.

    A inversão de controle como diretriz de projeto serve aos seguintes propósitos:
    - Há um desacoplamento da execução de uma determinada tarefa da implementação.
    - Cada módulo pode se concentrar no que foi projetado.
    - Os módulos não fazem suposições sobre o que outros sistemas fazem, mas dependem de seus contratos.
    - Substituir módulos não tem efeito colateral em outros módulos

Vou manter as coisas abstratas aqui, você pode visitar os links a seguir para uma compreensão detalhada do tópico.

Uma boa leitura com exemplo

Explicação detalhada

VdeX
fonte
11

No Spring, os objetos são fracamente acoplados, ou seja, cada classe é independente uma da outra, de modo que tudo pode ser testado individualmente. Mas ao usar essas classes, uma classe pode ser dependente de outras classes que precisam ser instanciadas primeiro.

Então, dizemos ao spring que a classe A é dependente da classe B. Assim, ao criar o bean (como a classe) para a classe A, ele instancia a classe B antes da classe A e injeta isso na classe A usando métodos setter ou construtor de DI. Ou seja, estamos dizendo à primavera a dependência em tempo de execução. Este é o DI.

Como estamos atribuindo a responsabilidade de criar objetos (beans), mantendo-os e suas agregações ao Spring em vez de codificá-lo, nós o chamamos de Inversão de Controle (IOC).

Venkateswara Rao
fonte
7

Inversão de controle (IOC):

IoC é um padrão de design que descreve a inversão do fluxo de controle em um sistema, de forma que o fluxo de execução não seja controlado por uma parte central do código. Isso significa que os componentes devem depender apenas de abstrações de outros componentes e não são responsáveis ​​por lidar com a criação de objetos dependentes. Em vez disso, as instâncias do objeto são fornecidas em tempo de execução por um contêiner IoC por meio de injeção de dependência (DI).

O IoC permite um design de software melhor que facilita a reutilização, o acoplamento fraco e o teste fácil de componentes de software.

Injeção de Dependência (DI):

DI é uma técnica para passar dependências para o construtor de um objeto. Se o objeto foi carregado do contêiner, suas dependências serão fornecidas automaticamente pelo contêiner. Isso permite que você consuma uma dependência sem ter que criar manualmente uma instância. Isso reduz o acoplamento e oferece maior controle sobre o tempo de vida das instâncias de objeto.

clique para ver mais

Greesh Kumar
fonte
6

Spring: Spring é o contêiner de “Inversão de Controle” para a plataforma Java.

Inversão de controle (IoC): Inversão de controle (IoC) é uma prática de programação orientada a objetos em que o acoplamento de objetos é limitado em tempo de execução por um objeto "montador" e normalmente não são reconhecíveis em tempo de compilação usando análise estática.

Dependency Injection (DI): "Dependency Injection é um padrão de design de software que permite a remoção de dependências embutidas em código e torna possível alterá-las, seja em tempo de execução ou de compilação." -wiki.

Nadhu
fonte
Como isso é mais simples do que o que já está por aí (que é de onde essa resposta vem)? Isso não leva em consideração o pedido de simplicidade do OP, a menos que as aspas duplas em torno das terminologias tornem as coisas mais simples magicamente.
Chama de udun
6

Inversão de controle - significa dar o controle de criação e instanciar os beans spring para o contêiner Spring IOC e o único trabalho que o desenvolvedor faz é configurar os beans no arquivo xml do spring.

Injeção de dependência-

Considere uma classe Employee

class Employee { 
   private int id;
   private String name;
   private Address address;

   Employee() {
     id = 10;
     name="name";
     address = new Address();
   }


}

e considere o endereço da classe

class Address {
   private String street;
   private String city;

   Address() {
     street="test";
     city="test1";

  }
}

No código acima, os valores da classe de endereço serão definidos apenas quando a classe Employee for instanciada, que é uma dependência da classe Address da classe Employee. E o Spring resolve esse problema usando o conceito de injeção de dependência, fornecendo duas maneiras de injetar essa dependência.

  1. Injeção setter

Método setter na classe Employee que leva uma referência da classe Address

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Injeção de construtor

Construtor na classe Employee que aceita Address

Employee(Address addr) {
      this.address = addr;
}

Desta forma, os valores da classe Address podem ser configurados independentemente usando injeção setter / constructor.

Hetal Rachh
fonte
3

Inversão de controle é um princípio de projeto genérico de arquitetura de software que auxilia na criação de estruturas de software modulares e reutilizáveis ​​que são fáceis de manter.

É um princípio de design no qual o Fluxo de Controle é "recebido" da biblioteca genérica ou do código reutilizável.

Para entender melhor, vamos ver como costumávamos codificar em nossos primeiros dias de codificação. Em linguagens procedurais / tradicionais, a lógica de negócios geralmente controla o fluxo do aplicativo e "chama" o código / funções genéricas ou reutilizáveis. Por exemplo, em um aplicativo de console simples, meu fluxo de controle é controlado pelas instruções do meu programa, que podem incluir as chamadas para algumas funções reutilizáveis ​​gerais.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

Em contraste, com IoC, os Frameworks são o código reutilizável que "chama" a lógica de negócios.

Por exemplo, em um sistema baseado em Windows, uma estrutura já estará disponível para criar elementos de interface do usuário como botões, menus, janelas e caixas de diálogo. Quando escrevo a lógica de negócios do meu aplicativo, são os eventos do framework que chamam meu código de lógica de negócios (quando um evento é disparado) e NÃO o contrário.

Embora o código do framework não conheça minha lógica de negócios, ele ainda saberá como chamar meu código. Isso é feito usando eventos / delegados, retornos de chamada, etc. Aqui, o controle de fluxo é "Invertido".

Portanto, em vez de depender do fluxo de controle de objetos estaticamente vinculados, o fluxo depende do gráfico geral do objeto e das relações entre os diferentes objetos.

A injeção de dependência é um padrão de design que implementa o princípio IoC para resolver dependências de objetos.

Em palavras mais simples, ao tentar escrever código, você estará criando e usando classes diferentes. Uma classe (Classe A) pode usar outras classes (Classe B e / ou D). Portanto, as classes B e D são dependências da classe A.

Uma analogia simples seria um carro da classe. Um carro pode depender de outras classes como motor, pneus e muito mais.

A injeção de dependência sugere que, em vez das classes dependentes (classe Car aqui) criarem suas dependências (classe Engine e classe Tire), a classe deve ser injetada com a instância concreta da dependência.

Vamos entender com um exemplo mais prático. Considere que você está escrevendo seu próprio TextEditor. Entre outras coisas, você pode ter um corretor ortográfico que fornece ao usuário a facilidade de verificar os erros de digitação em seu texto. Uma implementação simples de tal código pode ser:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

À primeira vista, tudo parece rosado. O usuário escreverá algum texto. O desenvolvedor irá capturar o texto e chamar a função CheckSpellings e encontrará uma lista de erros de digitação que ele mostrará ao usuário.

Tudo parece funcionar muito bem até um belo dia, quando um usuário começa a escrever em francês no Editor.

Para fornecer suporte para mais idiomas, precisamos ter mais SpellCheckers. Provavelmente francês, alemão, espanhol etc.

Aqui, criamos um código fortemente acoplado com "English" SpellChecker estreitamente acoplado à nossa classe TextEditor, o que significa que nossa classe TextEditor é dependente de EnglishSpellChecker ou em outras palavras EnglishSpellCheker é a dependência do TextEditor. Precisamos remover essa dependência. Além disso, Nosso Editor de Texto precisa de uma maneira de manter a referência concreta de qualquer verificador ortográfico com base no critério do desenvolvedor em tempo de execução.

Portanto, como vimos na introdução do DI, ele sugere que a classe deve ser injetada com suas dependências. Portanto, deve ser responsabilidade do código de chamada injetar todas as dependências na classe / código chamado. Portanto, podemos reestruturar nosso código como

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

Em nosso exemplo, a classe TextEditor deve receber a instância concreta do tipo ISpellChecker.

Agora, a dependência pode ser injetada em um Construtor, uma Propriedade Pública ou um método.

Vamos tentar mudar nossa classe usando Constructor DI. A classe TextEditor alterada será semelhante a:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Para que o código de chamada, ao criar o editor de texto, possa injetar o Tipo de SpellChecker apropriado na instância do TextEditor.

Você pode ler o artigo completo aqui

Amrit
fonte
1

A maneira tradicional de obter uma instância de endereço em Employee seria criando uma nova instância da classe Address. Spring cria todos os objetos dependentes para nós, portanto, não precisamos nos preocupar com o objeto.

Portanto, no Spring, dependemos apenas do container spring que nos fornece o objeto de dependência.

SumataPatil
fonte
1

IOC é a técnica em que você permite que outra pessoa crie o objeto para você. E a outra pessoa em caso de primavera é o contêiner IOC.

Injeção de dependência é uma técnica em que um objeto fornece a dependência de outro objeto.

demônio
fonte