Why use constructor-based dependency injection?
🇺🇸 Today I want to talk about something that, in practice, often doesn’t get the attention it deserves in Java applications using Spring — but that can greatly simplify a developer’s life and improve the overall quality of the software we write: constructor-based dependency injection.
We essentially have three ways to inject dependencies:
If I had to make a guess, I’d say that if you open the Spring application you’re currently working on, you’ll most likely find the majority of @Autowired annotations being used directly on bean fields.
Does it work? Yes. Is it the best approach? Not always — and in my opinion, it should often be avoided.
Whenever I write a new bean for my application, I strongly prefer constructor injection, mainly for the following reasons:
1 - Testability
When writing tests for a class that uses constructor injection, there’s no need to rely on reflection or specific frameworks to “force” dependency injection.
All dependencies are explicit and can be easily mocked at object creation time, making tests simpler, clearer, and more reliable.
2 - Single Responsibility Principle
As part of the SOLID principles, this rule works as an excellent design thermometer.
When the number of constructor parameters starts growing too much, it’s usually a clear sign that the class is taking on more responsibilities than it should — an early warning that refactoring might be needed.
3 - Readability and maintainability
By looking at a class constructor, anyone can quickly understand what that class depends on to function.
This improves code readability, makes maintenance easier, and reduces the cognitive load for anyone who needs to work on or evolve that part of the system in the future.
And you — have you ever stopped to think about how you choose to inject dependencies in your day-to-day work?
Recommended by LinkedIn
Por que utilizar injeção de dependência via construtor?
🇧🇷 Hoje quero falar sobre algo que, na prática, muitas vezes não recebe a devida atenção em aplicações Java com Spring — mas que pode facilitar bastante a vida do desenvolvedor e elevar a qualidade do software que escrevemos: a injeção de dependência via construtor.
Temos basicamente três formas de injetar dependências:
Se eu tivesse que arriscar um palpite, diria que, se você abrir agora a aplicação Spring em que está trabalhando, provavelmente encontrará a maioria das anotações @Autowired sendo usadas diretamente em campos dos beans.
Funciona? Sim. É a melhor abordagem? Nem sempre — e, na minha opinião, muitas vezes deveria ser evitada.
Sempre que vou escrever um novo bean para minha aplicação, dou preferência à injeção via construtor, principalmente pelos seguintes motivos:
1 - Testabilidade
Ao escrever testes para uma classe que utiliza injeção via construtor, não há necessidade de recorrer à reflexão ou a frameworks específicos para “forçar” a injeção de dependências.
Todas as dependências ficam explícitas e podem ser facilmente mockadas no momento da criação do objeto, tornando os testes mais simples, claros e confiáveis.
2 - Princípio da Responsabilidade Única
Como parte do acrônimo SOLID, esse princípio funciona como um excelente termômetro de design.
Quando o número de parâmetros do construtor começa a crescer demais, isso geralmente é um sinal claro de que a classe está assumindo mais responsabilidades do que deveria — um alerta precoce para refatoração.
3 - Legibilidade e manutenção
Ao olhar para o construtor de uma classe, qualquer pessoa consegue entender rapidamente do que aquela classe depende para funcionar.
Isso melhora a leitura do código, facilita a manutenção e reduz o esforço cognitivo de quem precisa trabalhar ou evoluir aquela parte do sistema no futuro.
E você — já parou para refletir sobre como escolhe injetar suas dependências no dia a dia?
Thank you for sharing your perspective on dependency injection.
My 'favorite' way to do dependency injection is by using @RequiredArgsConstructor and declaring final attributes on the class. The class ends up much cleaner :)