it-swarm.com.de

Wie genau funktioniert der Spring BeanPostProcessor?

Ich studiere für die Spring Core-Zertifizierung und habe einige Zweifel, wie Spring mit dem Bohnen-Lebenszyklus umgeht und insbesondere mit dem Bohnen-Postprozessor.

Also habe ich dieses Schema:

enter image description here

Mir ist ziemlich klar, was es bedeutet:

Die folgenden Schritte finden in der Phase Load Bean Definitions statt:

  • Die Klassen @ Configuration werden verarbeitet und/oder @ Components werden gesucht und/oder XML-Dateien werden analysiert.

  • Bean-Definitionen zu BeanFactory hinzugefügt (jede unter ihrer ID indiziert)

  • Special BeanFactoryPostProcessor Aufgerufene Beans können die Definition aller Beans ändern (z. B. für die Ersetzungen von Eigenschaften-Platzhalter-Werten).

In der Bohnenerstellungsphase finden dann folgende Schritte statt:

  • Standardmäßig wird jede Bean eifrig instanziiert (in der richtigen Reihenfolge erstellt, wobei die Abhängigkeiten eingefügt werden).

  • Nach der Abhängigkeitsinjektion durchläuft jede Bohne eine Nachverarbeitungsphase, in der eine weitere Konfiguration und Initialisierung erfolgen kann.

  • Nach der Nachbearbeitung ist das Bean vollständig initialisiert und einsatzbereit (wird anhand seiner ID verfolgt, bis der Kontext zerstört ist).

Ok, das ist mir ziemlich klar und ich weiß auch, dass es gibt zwei Arten von Bohnen-Postprozessoren das sind:

  • Initializers: Initialisiert das Bean, wenn Sie dazu aufgefordert werden (d. H. @PostConstruct).

  • und Alles andere:, das zusätzliche Konfiguration zulässt und kann vor oder nach dem Initialisierungsschritt ausgeführt werden

Und ich poste diese Folie:

enter image description here

Mir ist also sehr klar, was die Initialisierer Bean-Postprozessoren (das sind die mit @ PostContruct Annotation annotierten Methoden, die automatisch unmittelbar nach den Setter-Methoden aufgerufen werden) (so nach der Abhängigkeitsinjektion), und ich weiß, dass ich damit einen Initialisierungsbatch ausführen kann (wie im vorherigen Beispiel).

Aber was genau repräsentiert der andere Bohnen-Postprozessor? Was meinen wir, wenn wir sagen, dass diese Schritte ausgeführt werden vor oder nach der Initialisierungsphase?

Also werden meine Beans instanziiert und ihre Abhängigkeiten injiziert, sodass die Initialisierungsphase abgeschlossen ist (durch Ausführen einer mit @ PostContruct annotierten Methode). Was ist damit gemeint, dass vor der Initialisierungsphase ein Bean Post Processor verwendet wird? Dies bedeutet, dass dies vor der Ausführung der mit @ PostContruct annotierten Methode geschieht. Bedeutet dies, dass dies vor der Abhängigkeitsinjektion geschehen könnte (bevor die Setter-Methoden aufgerufen werden)?

Und was genau meinen wir, wenn wir sagen, dass es ausgeführt wird nach dem Initialisierungsschritt. Es bedeutet, dass es danach zur Ausführung einer mit @ PostContruct annotierten Methode kommt, oder was?

Ich kann mir leicht vorstellen, warum ich eine mit @ PostContruct gekennzeichnete Methode benötige, aber ich kann kein typisches Beispiel für die andere Art von Bean-Postprozessor finden. Können Sie mir ein typisches Beispiel dafür zeigen, wann dies der Fall ist? gebraucht?

77
AndreaNobili

Spring doc erklärt die BPPs unter Anpassen von Beans mit BeanPostProcessor . BPP-Beans sind eine spezielle Art von Beans, die vor allen anderen Beans erstellt werden und mit neu erstellten Beans interagieren. Mit diesem Konstrukt können Sie in Spring das Lebenszyklusverhalten einfach anpassen, indem Sie selbst ein BeanPostProcessor implementieren.

Mit einem benutzerdefinierten BPP wie

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}

aufgerufen werden und den Klassen- und Bean-Namen für jede erstellte Bean ausdrucken.

Um zu verstehen, wie die Methode zum Lebenszyklus des Beans passt und wann genau die Methode aufgerufen wird, lesen Sie docs

postProcessBeforeInitialization (Object bean, String beanName) Wenden Sie diesen BeanPostProcessor auf die angegebene neue Bean-Instanz an, bevor Sie Bean-Initialisierungs-Callbacks ausführen (z. B. afterPropertiesSet von InitializingBean oder eine benutzerdefinierte init-Methode) ).

postProcessAfterInitialization (Object bean, String beanName) Wenden Sie diesen BeanPostProcessor nach einem Bean-Initialisierungs-Callback (wie dem afterPropertiesSet von InitializingBean oder einer benutzerdefinierten init-Methode) auf die angegebene neue Bean-Instanz an ).

Das Wichtige ist auch das

Die Bean wird bereits mit Eigenschaftswerten gefüllt.

Für was betrifft die Beziehung mit dem @PostConstruct Beachten Sie, dass diese Annotation ein bequemer Weg ist, eine postProcessAfterInitialization -Methode zu deklarieren. Spring wird darauf aufmerksam, wenn Sie entweder CommonAnnotationBeanPostProcessor registrieren oder <context:annotation-config /> in der Bean-Konfigurationsdatei. Ob die @PostConstruct Methode wird vor oder nach jedem anderen postProcessAfterInitialization ausgeführt, abhängig von der Eigenschaft order

Sie können mehrere BeanPostProcessor-Instanzen konfigurieren und die Reihenfolge steuern, in der diese BeanPostProcessors ausgeführt werden, indem Sie die order-Eigenschaft festlegen.

38
Master Slave

Das typische Beispiel für einen Bean-Postprozessor ist, wenn Sie die ursprüngliche Bean in eine Proxy-Instanz einbinden möchten, z. bei Verwendung des @Transactional Anmerkung.

Dem Bean-Postprozessor wird die ursprüngliche Instanz des Beans übergeben, er kann alle Methoden auf dem Ziel aufrufen, er erhält jedoch auch die tatsächliche Bean-Instanz, die im Anwendungskontext gebunden werden sollte, was bedeutet, dass er tatsächlich jede zurückgeben kann Objekt, das es will. Das typische Szenario, in dem dies nützlich ist, besteht darin, dass der Bean-Postprozessor das Ziel in eine Proxy-Instanz einschließt. Alle Aufrufe an der Bean, die im Anwendungskontext gebunden sind, werden durch den Proxy geleitet, und der Proxy kann dann vor und/oder nach Aufrufe an der Ziel-Bean eine gewisse Magie ausführen, z. AOP oder Transaktionsmanagement.

25
marthursson

Der Unterschied ist, dass BeanPostProcessor sich in die Kontextinitialisierung einhakt und dann postProcessBeforeInitialization und postProcessAfterInitialization für alle definierten Beans aufruft.

Aber @PostConstruct wird nur für die bestimmte Klasse verwendet, die Sie nach der Konstruktor- oder Set-Methode für die Bean-Erstellung anpassen möchten.

3
Tam Le