Sobes.tech
Junior

Qual é a característica da injeção de dependências (Dependency Injection)?

sobes.tech IA

Resposta da IA

A característica principal da injeção de dependências (DI) é que a criação e gestão das dependências de um objeto são transferidas de dentro do próprio objeto para fora, geralmente para um contêiner IoC (Inversão de Controle). Em vez de o objeto criar ou encontrar as suas dependências, estas são "injetadas" de fora.

As principais vantagens e características do DI:

  • Separação de responsabilidades: A classe não é responsável por criar as suas dependências.
  • Testabilidade: As dependências podem ser facilmente substituídas por mocks ou stubs durante testes unitários.
  • Flexibilidade: É fácil alterar as implementações das dependências sem modificar o código que as utiliza.
  • Menor acoplamento: Os componentes tornam-se menos fortemente ligados, o que melhora a manutenção.

Formas de injeção:

  • Através do construtor (Constructor Injection): As dependências são passadas através do construtor da classe. É a forma mais preferida, pois garante a disponibilidade das dependências desde a criação do objeto.

    // Classe com dependência
    public class MyService {
        private MyDependency dependency;
    
        // Injeção através do construtor
        public MyService(MyDependency dependency) {
            this.dependency = dependency;
        }
    
        // Uso da dependência
        public void doSomething() {
            dependency.performAction();
        }
    }
    
    // Dependência
    public interface MyDependency {
        void performAction();
    }
    
    // Implementação da dependência
    public class MyDependencyImpl implements MyDependency {
        @Override
        public void performAction() {
            System.out.println("Ação realizada!");
        }
    }
    
  • Através do setter (Setter Injection): As dependências são passadas através de métodos públicos setters. Permite criar objetos com dependências conforme necessário, mas requer verificações adicionais de null e não garante a presença de todas as dependências imediatamente.

    // Classe com dependência
    public class AnotherService {
        private AnotherDependency dependency;
    
        // Construtor vazio
        public AnotherService() {
        }
    
        // Injeção através do setter
        public void setDependency(AnotherDependency dependency) {
            this.dependency = dependency;
        }
    
        // Uso da dependência
        public void doSomethingElse() {
            if (dependency != null) {
                dependency.anotherAction();
            } else {
                System.out.println("Dependência não definida!");
            }
        }
    }
    
    // Dependência
    public interface AnotherDependency {
        void anotherAction();
    }
    
    // Implementação da dependência
    public class AnotherDependencyImpl implements AnotherDependency {
        @Override
        public void anotherAction() {
            System.out.println("Outra ação realizada!");
        }
    }
    
  • Através do campo (Field Injection): As dependências são injetadas diretamente nos campos da classe usando anotações. É a mais simples em sintaxe, mas torna a classe dependente do framework DI e dificulta testes sem o framework.

    import org.springframework.beans.factory.annotation.Autowired;
    
    // Classe com dependência
    public class SomeOtherService {
    
        // Injeção através do campo (usando anotação Spring)
        @Autowired
        private YetAnotherDependency dependency;
    
        // Uso da dependência
        public void doYetAnotherThing() {
            dependency.performYetAnotherAction();
        }
    }
    
    // Dependência
    public interface YetAnotherDependency {
        void performYetAnotherAction();
    }
    
    // Implementação da dependência
    public class YetAnotherDependencyImpl implements YetAnotherDependency {
        @Override
        public void performYetAnotherAction() {
            System.out.println("Outra ação realizada!");
        }
    }
    

Comparação dos métodos de injeção:

Método de injeção Vantagens Desvantagens
Através do construtor Garante a presença das dependências, facilidade de testes, imutável Pode levar a "dependência por parâmetros" no construtor com muitas dependências
Através do setter Dependências opcionais, possibilidade de alterar dependências após criação Requer verificações de null, não garante o estado completo do objeto após criação
Através do campo Sintaxe concisa Forte dependência do framework DI, dificulta testes sem o framework

O DI é um princípio fundamental em muitos frameworks modernos (por exemplo, Spring, CDI) e promove a criação de aplicações desacopladas e facilmente testáveis.