No Spring, @Autowired não deveria ser seu padrão
Em muito projeto Spring, o uso de @Autowired em atributo virou reflexo.
O problema é que isso quase nunca aparece como problema no primeiro dia.
O código compila, a aplicação sobe e a classe parece pronta.
Mas, conforme o sistema cresce, fica mais difícil enxergar do que cada classe depende, escrever testes simples e perceber quando um serviço está assumindo responsabilidades demais.
Funciona, mas cria um problema silencioso: a dependência deixa de aparecer como parte explícita do contrato do objeto.
No Spring atual, na maioria dos casos, @Autowired nem é necessário.
O que muda na prática
Se uma classe tem um único construtor, o Spring já sabe que deve usá-lo para injeção.
Com injeção por construtor, a dependência aparece logo na entrada da classe.
Ela deixa de ser um detalhe escondido em atributo e passa a fazer parte da definição do objeto.
O resultado é simples: o código fica mais claro, o teste fica mais direto e a classe passa a dizer com mais honestidade do que precisa para existir.
Isso não quer dizer que @Autowired desaparece de todo cenário.
Às vezes ele ainda aparece no construtor, especialmente em código antigo ou em classes com mais de um construtor, quando o Spring precisa saber qual caminho usar.
Também pode aparecer em métodos setter, normalmente quando a dependência é opcional ou precisa ser resolvida depois da criação do objeto.
Mas esse é o ponto: esses casos são exceção de desenho, não o padrão mais saudável para dependências obrigatórias.
Um exemplo comparativo
Com @Autowired em campo:
@Service
public class PedidoService {
@Autowired
private EmailService emailService;
}
A dependência existe, mas fica escondida no corpo da classe.
Agora com injeção por construtor:
@Service
public class PedidoService {
private final EmailService emailService;
public PedidoService(EmailService emailService) {
this.emailService = emailService;
}
}
Aqui, se PedidoService precisa de EmailService, isso aparece imediatamente.
Esse formato também força uma leitura melhor da classe.
Se o construtor começar a crescer demais, o problema fica visível rápido.
Isso ajuda a perceber acoplamento excessivo e classes com responsabilidade demais, algo que o uso de @Autowired em campo costuma esconder por mais tempo.
Onde isso encosta em Dependency Injection
Isso conversa com os posts sobre IoC, Bean e DI.
O Spring cria e conecta os objetos, mas a classe ainda precisa declarar com clareza do que depende.
Esse é o ponto central: Dependency Injection não é esconder dependências para o framework resolver depois.
É declarar dependências de forma explícita para que o container possa montar a aplicação com clareza.
O que isso muda no seu código
@Autowired não é o centro da injeção de dependência no Spring.
O centro é a classe declarar corretamente o que precisa.
Quando a dependência entra pelo construtor, o código conversa melhor com o modelo do framework e com quem vai manter a aplicação depois.
Por isso, o ponto que vale fixar é simples: constructor injection não é preciosismo de estilo.
É uma forma mais segura de deixar visível o desenho real da classe.
Quando a dependência fica escondida em atributo, o código continua rodando, mas o contrato fica mais fraco.
Em Spring, clareza de dependência não é detalhe. É parte da qualidade do design.
