Spring @Autowire on Properties vs Constructor
Więc skoro używam Springa, gdybym miał napisać usługę, która ma zależności, wykonałbym następujące czynności:
@Component
public class SomeService {
@Autowired private SomeOtherService someOtherService;
}
Natknąłem się teraz na kod, który używa innej konwencji, aby osiągnąć ten sam cel
@Component
public class SomeService {
private final SomeOtherService someOtherService;
@Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Rozumiem, że obie te metody zadziałają. Ale czy jest jakaś zaleta korzystania z opcji B? Dla mnie tworzy więcej kodu w klasie i teście jednostkowym. (Konieczność napisania konstruktora i brak możliwości użycia @InjectMocks)
Is there something I ' m zaginęła? Czy jest coś jeszcze, co konstruktor autowired robi poza dodaniem kodu do testów jednostkowych? Czy jest to bardziej preferowany sposób wstrzykiwania zależności?
3 answers
Tak, Opcja B (zwana injekcją konstruktora) jest w rzeczywistości zalecana zamiast injekcji w terenie i ma kilka zalet:
- zależności są wyraźnie określone. Nie ma sposobu, aby o niej zapomnieć podczas testowania lub tworzenia instancji obiektu w innych okolicznościach (jak tworzenie instancji bean jawnie w klasie config)
- zależności mogą być ostateczne, co pomaga w solidności i bezpieczeństwie nici
- nie potrzebujesz refleksji, aby ustawić zależności. InjectMocks jest nadal użyteczny, ale nie jest konieczny. Możesz po prostu tworzyć mocki samodzielnie i wstrzykiwać je, po prostu wywołując konstruktor
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-28 20:44:40
Wyjaśnię Ci prostymi słowami:
W Option (a), pozwalasz każdemu (w innej klasie poza / wewnątrz kontenera Spring) na tworzenie instancji za pomocą domyślnego konstruktora (jak new SomeService()
), co nie jest dobre, ponieważ potrzebujesz SomeOtherService
obiektu (jako zależności) dla twojego SomeService
.
Czy jest coś jeszcze, co konstruktor autowired robi poza dodaniem kodu do testów jednostkowych? Czy jest to bardziej preferowany sposób na uzależnienie zastrzyk?
Opcja (B) jest preferowanym podejściem, ponieważ nie pozwala na tworzenie obiektu SomeService
bez faktycznego rozwiązania zależności SomeOtherService
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 16:09:39
Autowired
constructors zapewnia hook, aby dodać własny kod przed zarejestrowaniem go w kontenerze spring. Załóżmy, że klasa SomeService
rozszerza inną klasę o nazwie SuperSomeService
i ma jakiś konstruktor, który przyjmuje nazwę jako swój argument. W tym przypadku konstruktor Autowired
działa poprawnie. Ponadto, jeśli masz inne elementy do zainicjowania, możesz to zrobić w konstruktorze przed zwróceniem instancji do kontenera spring.
public class SuperSomeService {
private String name;
public SuperSomeService(String name) {
this.name = name;
}
}
@Component
public class SomeService extends SuperSomeService {
private final SomeOtherService someOtherService;
private Map<String, String> props = null;
@Autowired
public SomeService(SomeOtherService someOtherService){
SuperSomeService("SomeService")
this.someOtherService = someOtherService;
props = loadMap();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 09:08:05