Dlaczego warto używać @PostConstruct?
W managed bean, {[0] } jest wywoływany po zwykłym konstruktorze obiektów Java.
Dlaczego miałbym używać @PostConstruct
do inicjalizacji przez bean,zamiast zwykłego konstruktora?
5 answers
Ponieważ po wywołaniu konstruktora, bean nie jest jeszcze zainicjalizowany - tzn. nie są wstrzykiwane żadne zależności. W metodzie
@PostConstruct
bean jest w pełni zainicjalizowany i można używać zależności.Ponieważ jest to umowa, która gwarantuje, że ta metoda będzie wywoływana tylko raz w cyklu życia bean. Może się zdarzyć (choć mało prawdopodobne), że fasola jest wielokrotnie inicjowana przez kontener w jego wewnętrznej pracy, ale gwarantuje to, że
@PostConstruct
będzie wywołana tylko raz.
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
2011-10-05 13:20:40
główny problem polega na tym, że:
W konstruktorze nie doszło jeszcze do iniekcji zależności*
*oczywiście z wyłączeniem iniekcji konstruktora
Przykład w świecie rzeczywistym:
public class Foo {
@Inject
Logger LOG;
@PostConstruct
public void fooInit(){
LOG.info("This will be printed; LOG has already been injected");
}
public Foo() {
LOG.info("This will NOT be printed, LOG is still null");
// NullPointerException will be thrown here
}
}
Ważne :
@PostConstruct
oraz @PreDestroy
zostały całkowicie usunięte w Javie 11.
Aby nadal z nich korzystać, musisz dodać javax.adnotacja-api JAR do twojego zależności.
Maven
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
Gradle
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
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-10-30 10:04:29
Jeśli twoja klasa wykonuje całą inicjalizację w konstruktorze, to {[0] } jest rzeczywiście zbędna.
Jednakże, jeśli twoja klasa ma swoje zależności wstrzykiwane za pomocą metod settera, to konstruktor klasy nie może w pełni zainicjować obiektu, a czasami trzeba wykonać inicjalizację po wywołaniu wszystkich metod settera, stąd przypadek użycia @PostConstruct
.
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
2010-08-04 14:46:59
Rozważ następujący scenariusz:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Ponieważ samochód musi być uruchamiany przed wtryskiem w polu, silnik punktu wtrysku jest nadal zerowy podczas wykonywania konstruktora, co skutkuje wyrażeniem NullPointerException.
Ten problem można rozwiązać poprzez JSR-330 Dependency Injection for Java constructor injection lub wspólne adnotacje JSR 250 dla adnotacji metody Java @PostConstruct.
@PostConstruct
JSR-250 definiuje common set of adnotations which has been included in Java SE 6.
Adnotacja PostConstruct jest używana w metodzie, która musi być wykonywany po wykonaniu iniekcji zależności w celu wykonania dowolnego inicjalizacja. Ta metoda musi być wywołana przed wprowadzeniem klasy do użytku. Ta adnotacja musi być obsługiwana na wszystkich klasach, które wsparcie dependency injection.
JSR-250 2.5 javax.adnotacja.PostConstruct
Adnotacja @PostConstruct pozwala na zdefiniowanie metod, które mają być wykonywane po utworzeniu instancji i wykonaniu wszystkich iniekcji.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Zamiast inicjalizacji w konstruktorze, kod jest przenoszony do metody z adnotacją @PostConstruct.
Przetwarzanie metod post-construct polega na znalezieniu wszystkich metod opatrzonych adnotacją @PostConstruct i wywołaniu ich po kolei.
private void processPostConstruct(Class type, T targetInstance) {
Method[] declaredMethods = type.getDeclaredMethods();
Arrays.stream(declaredMethods)
.filter(method -> method.getAnnotation(PostConstruct.class) != null)
.forEach(postConstructMethod -> {
try {
postConstructMethod.setAccessible(true);
postConstructMethod.invoke(targetInstance, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
});
}
Przetwarzanie metod post-construct musi być wykonywane po zakończeniu tworzenia instancji i iniekcji.
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-10-18 06:43:57
Również inicjalizacja oparta na konstruktorze nie będzie działać zgodnie z założeniami, gdy w grę wchodzi jakieś proxy lub remoting.
Ct zostanie wywołany za każdym razem, gdy EJB zostanie deserializowany i gdy zostanie utworzony nowy proxy dla niego...
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
2011-10-16 15:34:30