Spring @PostConstruct a atrybut metody init


103

Czy jest jakaś różnica między użyciem @PostConstructadnotacji a zadeklarowaniem tej samej metody, co init-methodw konfiguracji Spring XML?

Odpowiedzi:


153

Nie, praktycznie nie sądzę, żeby było jakakolwiek różnica, ale sposób ich działania ma określone priorytety. @PostConstruct, init-methodsą BeanPostProcessors.

  1. @PostConstructto adnotacja JSR-250, podczas gdy init-methodSpring jest sposobem na posiadanie metody inicjalizacji.
  2. Jeśli masz @PostConstructmetodę, zostanie ona wywołana najpierw przed wywołaniem metod inicjalizujących.
  3. Jeśli Twoja fasola implementuje InitializingBean i przesłonięcia afterPropertiesSet, najpierw @PostConstructjest wywoływana, afterPropertiesSeta następnie init-method.

Aby uzyskać więcej informacji, zapoznaj się z dokumentacją Springa .

Przed specyfikacją JSR 250 preferowano użycie metody init w xml, ponieważ oddziela ona klasy Java (ziarna) od wszelkich klas / adnotacji specyficznych dla wiosny. wtedy preferowano użycie metody init. Podczas tworzenia metody u można określić metodę, która ma być wywołana jako metoda inicjalizacji.

Teraz, wraz z wprowadzeniem specyfikacji JSR 250 w Java EE i wiosennym wsparciem tych adnotacji, zależność od frameworka sprężynowego została do pewnego stopnia ograniczona.

Muszę jednak przyznać, że dodanie tych rzeczy zwiększa czytelność kodu, więc oba podejścia mają zalety i wady.


23
Jeśli fasola używa więcej niż jednej z tych metod i zależy od kolejności inicjalizacji, będzie to strasznie złożone i niemożliwe do utrzymania.
Donal Fellows

2
@Donal Całkiem prawdziwe. Podawałem tylko informacje, jak to działa.
Aravind A,

1
Jest ważna różnica: musisz specjalnie skonfigurować Spring do przetwarzania adnotacji, aby @PostConstruct działał: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, ale musisz to wiedzieć, jeśli planujesz zdawać egzaminy certyfikacyjne;)
S.Klechkovski

@DonalFellows - Czy możesz uściślić swoją odpowiedź? Mam na myśli trudności napotykane, jeśli fasola zależy od kolejności inicjalizacji. Właściwie to chcę wiedzieć, który jest lepszy. PostConstruct lub Bean (initMethod = "init"), aby wykonać jakieś czynności inicjalizacyjne z beana, zanim obsłuży jakiekolwiek żądania?
Ayaskant

19

Nie ma żadnej różnicy. Wszystko zależy od tego, jak wolisz konfigurować swój system, a to kwestia osobistego wyboru. Ja wolę używać @PostConstructadnotacji dla mojego własnego kodu (ponieważ bean jest poprawnie skonfigurowany dopiero po wywołaniu metody) i używam init-methodpodczas tworzenia instancji fasoli z bibliotek innych niż Spring-aware (nie można tam oczywiście stosować adnotacji!) ale mogę całkowicie zrozumieć ludzi, którzy chcą to robić w taki czy inny sposób.



3

Jak widać na poniższym diagramie wywołania zwrotnego cyklu życia tworzenia fasoli .

Odwołanie zwrotne cyklu życia tworzenia fasoli

Ten 3 etap ma miejsce w wywołaniu zwrotnym cyklu życia tworzenia fasoli:

  1. Wspomina się, że @PostConstructzostanie nazwany.
  2. Jeśli InitializingBeanjest zaimplementowana, afterPropertiesSet()zostanie wywołana.
  3. Jeśli definicja fasoli zawiera init-methodlub @Bean(initmethod="..")wywołuje metodę init.

Ten diagram pochodzi z Pro Spring 5: Szczegółowy przewodnik po strukturze Spring i jej narzędziach


3

Nie może być różnica między @PostConstructa init-methodponieważ @PostConstructjest obsługiwany w postProcessAfterInitializationfazie inicjalizacji fasoli ( AbstractAutowireCapableBeanFactory.initializeBean()metoda) przez CommonAnnotationBeanPostProcessor, podczas gdy initmetoda jest wywoływana po zakończeniu postProcessBeforeInitializationfazy (iz tego sprawy, przed rozpoczęciem postProcessAfterInitializationfazy).
EDYCJA : Tak więc sekwencja to: 1) postProcessBeforeInitializationfaza, 2) wywołanie metody init, 3) postProcessAfterInitializationfaza, która wywołuje @PostConstructmetodę

(Na marginesie, oświadczenie z zaakceptowanej odpowiedzi

@PostConstruct, metoda-init to BeanPostProcessors

nie jest do końca poprawna: @PostConstructjest obsługiwana przez metodę BeanPostProcessor, initmetoda nie).

Nie będzie różnica jeśli niektóre (potencjalnie niestandardowa) BeanPostProcessor, który jest skonfigurowany ( Ordered.getOrder()) mają zostać wykonane po CommonAnnotationBeanPostProcessor, robi coś poważnego w jego postProcessBeforeInitializationmetodzie.
Nie ma żadnej różnicy w domyślnej konfiguracji Spring, BeanPostProcessorsponieważ wszystkie te, BeanPostProcessorsktóre są skonfigurowane do wykonania po CommonAnnotationBeanPostProcessor, nie robią nic w postProcessBeforeInitializationmetodzie.

Podsumowując, przyjęta odpowiedź i tym podobne są słuszne ... w 99% przypadków, a ten post jest tylko hołdem dla koncepcji „diabeł tkwi w szczegółach”


Cześć! Jest to mylące, jeśli PostConstruct działa przed metodą init, jak jest obsługiwany przez postProcessAfterInitialization, jeśli metoda init działa po postProcessBeforeInitialization i przed postProcessAfterInitialization ???
Maxrunner

@Maxrunner, przepraszam za zamieszanie i wielkie dzięki za informację! Właściwie nigdy nie chciałem powiedzieć, że PostConstruct działa przed metodą init. W każdym razie zaktualizowałem moją odpowiedź o kilka wyjaśnień
igor.zh

2

Pełny kod tutaj: https://github.com/wkaczurba/so8519187 ( spring-boot )

Korzystanie z adnotacji:

@Slf4j
@Component
public class MyComponent implements InitializingBean {

    @Value("${mycomponent.value:Magic}")
    public String value;

    public MyComponent() {
        log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
    }

    @PostConstruct
    public void postConstruct() {
        log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
    }

    @Override // init-method; overrides InitializingBean.afterPropertiesSet()
    public void afterPropertiesSet() {
        log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
    }   

    @PreDestroy
    public void preDestroy() {
        log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
    }
}

Dostaje nas:

Odświeżam org.springframework.context ...

MyComponent w konstruktorze: [null]
MyComponent in postConstruct: [Magic]
MyComponent in afterPropertiesSet: [Magic]
...

Rejestrowanie komponentów bean do wyświetlania JMX podczas uruchamiania
Uruchomiono aplikację DemoApplication w 0,561 sekundy (JVM działa w wersji 1.011)
Zamykanie org.springframework.context .. . Wyrejestrowywanie komponentów bean eksponowanych na JMX przy wyłączaniu

...
MyComponent w preDestroy: [Magic]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.