Aufrufen einer mit Annotationen versehenen @ Bean-Methode in der Spring Java-Konfiguration


97

Ich bin gespannt, wie die Federeinspritzung mit der @BeanAnnotation aufruft . Wenn ich @Beaneiner Methode eine Annotation hinzufüge und eine Instanz zurückgebe, muss Spring eine Bean erstellen, indem die Methode aufgerufen und die zurückgegebene Instanz abgerufen wird. Manchmal muss diese Bean jedoch verwendet werden, um andere Beans zu verkabeln oder anderen Code einzurichten. Die übliche Vorgehensweise besteht darin, die mit @BeanAnmerkungen versehene Methode aufzurufen , um eine Instanz abzurufen. Meine Frage ist, warum dies nicht dazu führt, dass mehrere Instanzen der Bean herumschweben.

Siehe zum Beispiel den folgenden Code (entnommen aus einer anderen Frage). Die entryPoint()Methode ist mit Anmerkungen versehen @Bean, daher würde ich mir vorstellen, dass der Frühling eine neue Instanz BasicAuthenticationEntryPointals Bohne erstellen wird . Dann rufen wir entryPoint()den Konfigurationsblock erneut auf, aber es scheint, als würde entryPoint()die Bean-Instanz zurückgegeben und nicht mehrmals aufgerufen (ich habe versucht, mich zu protokollieren, und habe nur einen Protokolleintrag erhalten). Möglicherweise könnten wir entryPoint()in anderen Teilen der Konfiguration mehrmals aufrufen , und wir würden immer dieselbe Instanz erhalten. Ist mein Verständnis davon richtig? Führt der Frühling eine magische Umschreibung der mit Anmerkungen versehenen Methoden durch @Bean?

@Bean
public BasicAuthenticationEntryPoint entryPoint() {
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthEntryPoint.setRealmName("My Realm");
    return basicAuthEntryPoint;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .exceptionHandling()
            .authenticationEntryPoint(entryPoint())
            .and()
        .authorizeUrls()
            .anyRequest().authenticated()
            .and()
        .httpBasic();       
}

Antworten:


129

Ja, tut Frühling etwas Magie . Überprüfen Sie die Spring Docs :

Hier kommt die Magie ins Spiel : Alle @ConfigurationKlassen werden beim Start mit CGLIB in Unterklassen unterteilt . In der Unterklasse überprüft die untergeordnete Methode den Container zuerst auf zwischengespeicherte Beans (mit Gültigkeitsbereich), bevor sie die übergeordnete Methode aufruft und eine neue Instanz erstellt.

Dies bedeutet, dass die Aufrufe von @BeanMethoden über CGLIB übertragen werden und daher die zwischengespeicherte Version der Bean zurückgegeben wird (eine neue wird nicht erstellt).

Der Standardbereich von @Beans ist SINGLETON, wenn Sie einen anderen Bereich angeben, z. B. wird PROTOTYPEder Aufruf an die ursprüngliche Methode übergeben.

Bitte beachten Sie, dass dies für statische Methoden nicht gilt . Gemäß den Frühlingsdokumenten:

Aufrufe statischer @BeanMethoden werden vom Container @Configurationaufgrund technischer Einschränkungen niemals abgefangen, auch nicht innerhalb von Klassen (wie weiter oben in diesem Abschnitt beschrieben): CGLIB-Unterklassen können nur nicht statische Methoden überschreiben. Infolgedessen weist ein direkter Aufruf einer anderen @BeanMethode eine Standard-Java-Semantik auf, was dazu führt, dass eine unabhängige Instanz direkt von der Factory-Methode selbst zurückgegeben wird.


Ist es möglich, auf diese Weise erstellte Beans zu überschreiben? Zum Beispiel habe ich eine Spring-definierte Klasse, die direkt eine Bean-Erstellungsmethode aufruft. Ich möchte, dass nicht die mit dieser Methode erstellte Bean verwendet wird, sondern eine, die ich selbst definiere (indem ich sie mit @Beanund kommentiere @Primary).
Fons

4
Ich erinnere mich aber auch daran, dass der Proxy (jdk oder CGLIB, je nachdem) nicht im Selbstaufruf funktionieren kann. Wie definiert @Configuration die Abhängigkeit zwischen Beans? Es verwendet genau Selbstaufruf
Nowhy

3
@Nowhy CGLib allows us to create proxy classes at runtime by creating sub class of specified class using Byte code generation. CGLib proxies are used in the case where Proxy is to be created for those class which does not have any interfaces or have methods which are not declared in the implementing interface. In diesem Fall erstellt CGLIB eine Unterklasse der @ Configuration-Klasse und überschreibt deren Methoden (einschließlich der @ Bean-Methode). Wenn wir also die @ Bean-Methode von einer anderen Methode aus aufrufen, rufen wir tatsächlich ihre überschriebene Version auf (dank der dynamischen Java-Bindung).
Flame239

Funktioniert selfInvocation AOP in @Component, wenn ich CHLIB verwende, um Proxys anstelle von Java Poxy zu erstellen?
Antoniossss
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.