Injeção de Dependência em Java: na prática do A ao Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Injeção de Dependência em Java: na prática



Injeção de Dependência (DI) — é um dos princípios-chave do desenvolvimento moderno em Java, que está na base de frameworks como Spring e Jakarta EE. Neste artigo, vamos analisar o que é injeção de dependências, por que ela é necessária e, o mais importante, como aplicá-la na prática com exemplos de código.



O que é Injeção de Dependência e por que é importante?



Injeção de Dependência é um padrão de projeto no qual um objeto recebe suas dependências de fora, em vez de criá-las por conta própria. Isso implementa o princípio Inversion of Control (IoC) — inversão de controle. Em vez de a classe gerenciar suas próprias dependências, o gerenciamento é transferido para um container ou fábrica externa.



Imagine que você está escrevendo um aplicativo para enviar notificações. Sem DI, seu código pode ser assim:



public class NotificationService {    private EmailSender emailSender = new EmailSender();

public void send(String message) { emailSender.send(message); }}


O problema é óbvio: NotificationService está rigidamente acoplado a EmailSender. Se você quiser adicionar SMS ou notificações Push, terá que reescrever toda a classe. Com Injeção de Dependência, esse problema é resolvido:



public class NotificationService {    private final MessageSender messageSender;

// A dependência é passada através do construtor public NotificationService(MessageSender messageSender) { this.messageSender = messageSender; }

public void send(String message) { messageSender.send(message); }}


Agora a classe depende da abstração MessageSender, e não de uma implementação concreta. Isso torna o código flexível, testável e escalável.



Formas de injeção de dependências em Java



Existem três maneiras principais de implementar DI em Java. Vamos analisar cada uma delas com exemplos.



1. Injeção via construtor (Constructor Injection)



Esta é a forma mais preferível. As dependências são passadas através dos parâmetros do construtor e geralmente são marcadas como final.



public class UserService {    private final UserRepository userRepository;    private final EmailService emailService;

public UserService(UserRepository userRepository, EmailService emailService) { this.userRepository = userRepository; this.emailService = emailService; }

public void registerUser(User user) { userRepository.save(user); emailService.sendWelcomeEmail(user.getEmail()); }}


Vantagens:

  • Dependências obrigatórias são explicitamente visíveis
  • O objeto está sempre em um estado válido
  • Excelente para objetos imutáveis (immutable)
  • Fácil de testar — basta passar objetos mock


2. Injeção via setters (Setter Injection)



As dependências são definidas através de métodos setter após a criação do objeto.



public class OrderService {    private PaymentGateway paymentGateway;

public void setPaymentGateway(PaymentGateway paymentGateway) { this.paymentGateway = paymentGateway; }

public void processOrder(Order order) { paymentGateway.charge(order.getTotal()); }}


Quando usar: Para dependências opcionais ou quando as dependências podem mudar durante a vida do objeto. No entanto, essa abordagem torna o objeto mutável e menos previsível.



3. Injeção via campo (Field Injection)



Mais frequentemente usada com frameworks através de anotações, como @Autowired no Spring.



public class ReportService {    @Autowired    private DataSource dataSource;

public Report generateReport() { return dataSource

Blogs

Book Recommendations