O que é o conceito de Dependency Injection no Spring?

A Injeção de Dependência (Dependency Injection) no Spring permite gerenciar e instanciar componentes automaticamente, seguindo o princípio da inversão de controle (IoC).

O que é o conceito de Dependency Injection no Spring?

A Injeção de Dependência (Dependency Injection - DI) é um dos conceitos fundamentais do Spring Framework. Ele permite que objetos sejam criados e gerenciados automaticamente pelo Spring Container, seguindo o princípio da Inversão de Controle (IoC).

1. Por que usar Injeção de Dependência?

Sem DI, teríamos que criar instâncias manualmente dentro das classes, o que dificulta o desacoplamento e os testes. Exemplo sem DI:

public class PedidoService {
    private final EmailService emailService = new EmailService();
}

O problema aqui é que PedidoService depende diretamente de EmailService, tornando o código rígido e difícil de modificar.

2. Como funciona a Injeção de Dependência no Spring?

No Spring, usamos @Autowired para que o framework injete automaticamente as dependências necessárias:

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class PedidoService {
    private final EmailService emailService;

    @Autowired
    public PedidoService(EmailService emailService) {
        this.emailService = emailService;
    }
}

Explicação:

  • @Service indica que a classe PedidoService será gerenciada pelo Spring.
  • @Autowired faz com que o Spring injete automaticamente a dependência EmailService.
  • Agora, PedidoService não precisa criar manualmente uma instância de EmailService.

3. Tipos de Injeção de Dependência no Spring

O Spring permite três tipos principais de injeção:

1. Injeção via Construtor (Recomendada)

@Service
public class PedidoService {
    private final EmailService emailService;

    @Autowired
    public PedidoService(EmailService emailService) {
        this.emailService = emailService;
    }
}
  • Vantagem: Garante que a dependência seja injetada no momento da criação do objeto.
  • Boa prática: Recomendado para classes imutáveis e testáveis.

2. Injeção via Setter

@Service
public class PedidoService {
    private EmailService emailService;

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}
  • Vantagem: Permite modificar a dependência após a criação do objeto.
  • Uso comum: Quando a injeção pode ser opcional.

3. Injeção Direta no Campo (Evitar)

@Service
public class PedidoService {
    @Autowired
    private EmailService emailService;
}
  • Problema: Dificulta a criação de mocks para testes.
  • Recomendação: Evite esse método e prefira injeção via construtor.

4. Gerenciando Dependências com @Component, @Service e @Repository

O Spring permite registrar beans automaticamente no contexto com diferentes anotações:

Anotação Uso
@Component Define um bean genérico gerenciado pelo Spring
@Service Indica um serviço de regra de negócio
@Repository Específico para classes de acesso a banco de dados

Exemplo:

@Component
public class EmailService {
    public void enviarEmail(String destinatario) {
        System.out.println("Enviando e-mail para " + destinatario);
    }
}

5. Criando Beans Manualmente com @Bean

Além de usar @Component, podemos criar beans personalizados com @Bean:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public EmailService emailService() {
        return new EmailService();
    }
}

Diferencial: Permite maior controle sobre a criação dos objetos.

Conclusão

A Injeção de Dependência simplifica o gerenciamento de objetos e melhora o desacoplamento no código. No Spring, o uso de @Autowired, @Component e @Bean permite criar aplicações modulares e fáceis de testar.

A Injeção de Dependência é um conceito essencial no desenvolvimento de software moderno. Com o Spring Boot, ela se torna uma prática simples e eficaz para gerenciar componentes de forma desacoplada. Ao invés de instanciar objetos manualmente, o Spring se encarrega de criar e gerenciar essas instâncias, tornando a aplicação mais flexível, testável e escalável. Esse conceito é amplamente utilizado em arquiteturas baseadas em microsserviços e APIs REST.

Algumas aplicações:

  • Facilita o gerenciamento de componentes no Spring Boot
  • Permite construir aplicações desacopladas e modulares
  • Melhora a testabilidade ao facilitar o uso de mocks
  • Reduz a complexidade na criação e manutenção de objetos

Dicas para quem está começando

  • Prefira injeção via construtor para melhor testabilidade
  • Evite injeção direta em atributos (@Autowired no campo)
  • Use @Service, @Repository e @Component corretamente
  • Registre beans personalizados com @Bean quando necessário

Contribuições de Rodrigo Farias

Compartilhe este tutorial: O que é o conceito de Dependency Injection no Spring

Compartilhe este tutorial

Continue aprendendo:

Como fazer paginação de resultados no Spring Boot

A paginação no Spring Boot permite otimizar consultas ao banco de dados, retornando dados de forma segmentada com Spring Data JPA e Pageable.

Tutorial anterior

Como consumir uma API externa em Java

Consumir APIs externas em Java pode ser feito usando RestTemplate ou WebClient para enviar requisições HTTP e receber respostas.

Próximo tutorial