Spring @ PostConstruct vs. init-method-Attribut


103

Gibt es einen Unterschied zwischen der Verwendung der @PostConstructAnnotation und der Deklaration derselben Methode wie init-methodin der Spring XML-Konfiguration?

Antworten:


153

Nein, praktisch glaube ich nicht, dass es einen Unterschied gibt, aber es gibt Prioritäten in der Art und Weise, wie sie funktionieren. @PostConstruct, init-methodSind BeanPostProcessors.

  1. @PostConstruct ist eine JSR-250-Annotation während init-method Spring eine Initialisierungsmethode verwendet.
  2. Wenn Sie eine @PostConstructMethode haben, wird diese zuerst aufgerufen, bevor die Initialisierungsmethoden aufgerufen werden.
  3. Wenn Ihre Bean InitializingBean implementiert und überschreibt afterPropertiesSet, wird zuerst @PostConstructaufgerufen, dann das afterPropertiesSetund dann init-method.

Weitere Informationen finden Sie in der Referenzdokumentation von Spring .

Vor den JSR 250-Spezifikationen wurde die Verwendung der init-Methode in XML bevorzugt, da Java-Klassen (Beans) von allen springspezifischen Klassen / Anmerkungen entkoppelt werden. Wenn Sie also eine Bibliothek erstellen, die nicht von Spring-Infrastruktur-Beans abhängig sein muss Dann wurde die Verwendung der Init-Methode bevorzugt. Während der Erstellungsmethode können Sie die Methode angeben, die als Initialisierungsmethode aufgerufen werden muss.

Mit der Einführung der JSR 250-Spezifikationen in Java EE und der Unterstützung dieser Anmerkungen durch Federn wurde die Abhängigkeit vom Federgerüst bis zu einem gewissen Grad verringert.

Aber ich muss zugeben, dass das Hinzufügen dieser Dinge die Lesbarkeit von Code erhöht. Es gibt also Vor- und Nachteile beider Ansätze.


22
Wenn eine Bean mehr als eine dieser Methoden verwendet und sich auf die Reihenfolge der Initialisierung verlässt, wird dies schrecklich komplex und nicht wartbar sein.
Donal Fellows

2
@Donal Ganz richtig. Ich habe nur Informationen darüber geliefert, wie das funktioniert.
Aravind A

1
Es gibt einen wichtigen Unterschied: Sie müssen Spring speziell so konfigurieren, dass Anmerkungen verarbeitet werden, damit @PostConstruct funktioniert: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, aber Sie müssen dies wissen, wenn Sie Zertifizierungsprüfungen
ablegen möchten

@DonalFellows - Können Sie bitte Ihre Antwort ausarbeiten? Ich meine die Schwierigkeiten, mit denen eine Bohne konfrontiert ist, wenn sie sich auf die Reihenfolge der Initialisierung stützt. Eigentlich möchte ich wissen, welches besser ist. PostConstruct oder Bean (initMethod = "init"), um einige Initialisierungsaufgaben von einer Bean aus auszuführen, bevor sie Anforderungen bedient?
Ayaskant

19

Es gibt keinen wirklichen Unterschied. Es hängt davon ab, wie Sie Ihr System lieber konfigurieren, und das ist eine Frage der persönlichen Wahl. Ich selbst benutze es lieber@PostConstruct Anmerkungen für meinen eigenen Code (da die Bean erst nach dem Aufruf der Methode korrekt konfiguriert wird) und verwende sie init-methodbeim Instanziieren von Beans aus nicht Spring-fähigen Bibliotheken (dort können natürlich keine Anmerkungen angewendet werden!). Aber ich kann die Leute total verstehen, die alles auf die eine oder andere Weise machen wollen.



3

Wie Sie im folgenden Diagramm von Bean Creation Life-Cycle Callback sehen können .

Lebenszyklus-Rückruf für die Bohnenerstellung

Dieser dreistufige Schritt erfolgt im Bean Creation Life-Cycle Callback:

  1. Es wird erwähnt, @PostConstructdass aufgerufen wird.
  2. Wenn InitializingBeanimplementiert, afterPropertiesSet()wird aufgerufen.
  3. Wenn die Bean-Definition enthält init-methododer @Bean(initmethod="..")dann die init-Methode aufruft.

Dieses Diagramm stammt aus Pro Spring 5: Eine ausführliche Anleitung zum Spring Framework und seinen Tools


3

Es könnte seinen Unterschied zwischen @PostConstructund init-methodweil @PostConstructin der Handhabung postProcessAfterInitializationPhase der Bohne Initialisierung ( AbstractAutowireCapableBeanFactory.initializeBean()Methode) durch CommonAnnotationBeanPostProcessor, während initVerfahren nach dem Abschluss der aufgerufen werden postProcessBeforeInitializationPhase (und, für diese Angelegenheit, vor dem Beginn der postProcessAfterInitializationPhase).
EDIT : Die Sequenz lautet also: 1) postProcessBeforeInitializationPhase, 2) initMethode wird aufgerufen, 3) postProcessAfterInitializationPhase, die aufruft@PostConstruct Methode

(Als Randnotiz eine Aussage aus der akzeptierten Antwort

@PostConstruct, init-Methode sind BeanPostProcessors

ist nicht ganz richtig: @PostConstructwird von a behandelt BeanPostProcessor, initMethode nicht.)

Es wird einen Unterschied geben, ob einige (möglicherweise benutzerdefinierte) BeanPostProcessor, die mit ( Ordered.getOrder()) konfiguriert sind , um danach ausgeführt zu werden CommonAnnotationBeanPostProcessor, etwas Ernstes in ihrer postProcessBeforeInitializationMethode tun .
Es gibt keinen Unterschied zur Standard-Spring-Konfiguration von, BeanPostProcessorsda alle, die BeanPostProcessorsfür die Ausführung nach konfiguriert sind CommonAnnotationBeanPostProcessor, nichts tunpostProcessBeforeInitialization Methode .

Zusammenfassend ist die akzeptierte Antwort und dergleichen richtig ... in 99% der Fälle, und dieser Beitrag ist nur eine Hommage an ein Konzept "Der Teufel steckt im Detail".


Hallo! Dies ist verwirrend, wenn PostConstruct vor der init-Methode ausgeführt wird. Wie wird es von der postProcessAfterInitialization behandelt, wenn die init-Methode nach der postProcessBeforeInitialization und vor der postProcessAfterInitialization ausgeführt wird?
Maxrunner

@ Maxrunner, Entschuldigung für die Verwirrung und vielen Dank für die Benachrichtigung! Eigentlich wollte ich nie sagen, dass PostConstruct vor der init-Methode ausgeführt wird. Wie auch immer, ich habe meine Antwort mit einigen Klarstellungen aktualisiert
igor.zh

2

Vollständiger Code hier: https://github.com/wkaczurba/so8519187 ( Spring-Boot )

Verwenden von Anmerkungen:

@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
    }
}

Erhält uns:

Aktualisieren von org.springframework.context ...

MyComponent im Konstruktor: [null]
MyComponent in postConstruct: [Magic]
MyComponent in afterPropertiesSet: [Magic]
...

Registrieren von Beans für JMX-Exposition beim Start
Started DemoApplication in 0,561 Sekunden (JVM läuft für 1.011)
Schließen von org.springframework.context .. Aufheben der Registrierung von JMX-exponierten Beans beim Herunterfahren

...
MyComponent in preDestroy: [Magic]

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.