Se você trabalha com Spring Boot há algum tempo, sabe o quanto a injeção de dependências do framework facilita no desenvolvimento e permite que você tenha um maior desacoplamento entre componentes do seu software.
Mas antes que eu responda a pergunta do título desse artigo, do que se trata a injeção de dependências, ou Dependency Injection (DI), e de que forma podemos injetar as dependências no Spring Boot?
Spring Boot e Dependency Injection
Uma aplicação é composta por diversos objetos que interagem uns com os outros para cumprir objetivos determinados. Dessa forma a injeção de dependências num sentido mais simples pode ser compreendida como a injeção de objetos para um objeto ou framework em tempo de execução. Essa injeção pode ocorrer de três formas no Spring: field injection, setter injection ou constructor injection.
Field injection é quando anotamos o field com @Autowired, como no exemplo abaixo:
@Component
public class MyComponent {
@Autowired
private MyService myService;
// Business logic goes here
}
Setter injection é quando anotamos o setter do field com @Autowired, como no exemplo abaixo:
@Component
public class MyComponent {
private MyService myService;
@Autowired
public void setMyService(MyService service) {
this.myService = service;
}
// Business logic goes here
}
Constructor injection é quando declaramos o field com o modificador final e injetamos no construtor da classe, como no exemplo abaixo:
@Component
public class MyComponent {
private final MyService myService;
public MyComponent(final MyService service) {
this.myService = service;
}
// Business logic goes here
}
Não devo usar @Autowired?
Não recomendo, mas aconselho que caso o faça, faça entendendo as consequências. Imagine que você inicia o desenvolvimento de um sistema e meses depois percebe que aquela classe de service cresceu muito e carrega consigo dezenas de dependências. Sempre que você precisou injetar uma nova dependência, bastou declarar o field e anotar com @Autowired, certo? É a maneira mais utilizada, é tão simples e rápido que você por vezes não para e reflete sobre o que está fazendo. Talvez se refletisse, perceberia que era o momento de refatorar partes do sistema para melhorar sua manutenção.
Nesse artigo quero te dar uma dica: utilize o constructor injection ao invés das opções com @Autowired pois os benefícios são muito maneiros: esse método evidencia o crescimento de sua classe, já que te obriga a refatorar o construtor a cada nova dependência, e também facilita sua vida na hora de escrever testes unitários.
O constructor injection é positivo para a escrita de testes unitários pois permite que você crie o mock das dependências de forma mais simples e com maior controle ao invés de depender de anotações do Mockito como o @InjectMocks. Pense por exemplo em um caso de teste em que você precise mockar parte das dependências mas uma em específico você precisa que seja a implementação real: injetando as dependências no construtor do componente em seu teste unitário você alcança isso com facilidade.
Leitura recomendada
Caso queira entender um pouco mais sobre o conceito de Dependency Injection, recomendo este ótimo artigo do Martin Fowler, intitulado “Inversion of Control Containers and the Dependency Injection pattern“.
Por hoje é isso. Caso tenha alguma crítica ou sugestão, utilize a caixa de comentários abaixo, seu feedback é muito bem vindo. Ah, caso não tenha entendido por que usei um Megazord como imagem deste artigo, pense em acoplamento. Até a próxima!
Be First to Comment