Spring tworzy obiekty (beany) i wstrzykuje im zależności, więc kod nie skleja wszystkiego ręcznie. Wstrzykiwanie przez konstruktor jest jawne, wspiera niemutowalność (`final`) i jest najłatwiejsze do testowania.
@Service
class UserService {
private final UserRepository repo;
UserService(UserRepository repo) {
this.repo = repo;
}
}
Odpowiedź zaawansowana
Głębiej
Dependency Injection (DI) to wzorzec, w którym zewnętrzny kontener (Spring) tworzy obiekty i dostarcza im zależności. W Springu robi to kontener IoC (ApplicationContext): tworzy beany, rozwiązuje wiring, zarządza cyklem życia i dokleja mechanizmy przekrojowe (AOP, transakcje, security).
Constructor injection jest preferowane, bo:
**Zależności są jawne**: jeśli kod się kompiluje, wymagane zależności są dostarczone.
**Niemutowalność**: pola mogą być `final` i inicjalizowane raz.
**Testowalność**: w testach jednostkowych możesz zrobić `new` bez Springa.
**Fail fast**: brakujący bean wychodzi na jaw przy starcie, a nie w runtime.
Praktyka
Konstruktor dla zależności wymaganych.
Dla zależności opcjonalnych: `Optional<T>` / `ObjectProvider<T>` albo rozdziel odpowiedzialności.
Jeśli konstruktor ma „za dużo” argumentów, to często sygnał zbyt dużej klasy.
Przykład
@Service
class UserService {
private final UserRepository repo;
private final Clock clock;
UserService(UserRepository repo, Clock clock) {
this.repo = repo;
this.clock = clock;
}
}