2012-05-10 5 views
9

Ich verwende Spring 3 AOP, und ich habe einen Aspekt, der Zugriff auf die HttpServletRequest erfordert. Es sieht etwa so aus:Spring AOP und Aspect Thread-Sicherheit für eine Autowired HTTPServletRequest Bean

@Aspect 
public class MyAspect { 

    @Autowired 
    private HttpServletRequest httpServletRequest; 

    public void init() { 
     // Do something once... 
    } 

    @Before("my pointcut here...") 
    private void myMethod() { 
     // I need the httpServletRequest... 
    } 

    @After("my pointcut here...") 
    private void myOtherMethod() { 
     // I need the httpServletRequest... 
    } 
} 

Und wie folgt konfiguriert ist:

<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" /> 

Ist die init-Methode nur einmal pro IoC-Container genannt, obwohl dies ein Aspekt ist, und ist die HttpServletRequest Thread-sicher ? Wenn dies nicht der Fall ist, was ist der beste Weg, um während der Ausführung des Hinweises darauf zu kommen und ihn threadsicher zu machen? Wenn es mir möglich ist, benutze ich keinen lokalen Thread.

Antwort

16

Ist die init-Methode aufgerufen nur einmal pro IoC Container

es einmal genannt wird pro jede Bean-Instanz. Wenn Bean einen Singleton-Bereich hat (was auch für Aspekte der Standardfall ist), wird es nur einmal aufgerufen. Sie haben jedoch keinen Zugriff auf die httpServletRequest innerhalb init() Methode - es gibt noch keine Anfrage!

ist die HttpServletRequest Thread-sicher

es nicht, aber keine Sorge ist. Das ist eigentlich viel komplexer als es aussieht. Sie injizieren eine HTTP-Servlet-Anfrage (und offensichtlich können mehrere Anfragen gleichzeitig zur Verfügung stehen) in ein Singleton-Objekt. Welcher wird eingespritzt? Keine (alle?) Von ihnen! Spring erstellt einige anspruchsvolle Proxy (Bereichsproxy) und jedes Mal, wenn Sie Methoden von injiziert zugreifen, delegiert sie an aktuellen (Thread) Anfrage. Auf diese Weise können Sie Ihre Aspekte in mehreren Threads sicher ausführen - jeder wird auf eine andere physische Anfrage reagieren.

Das ganze Verhalten ist in großen Details in 4.5.4.5 Scoped beans as dependencies beschrieben:

[...] Wenn Sie inject (zum Beispiel) wollen eine HTTP-Anforderung Bohne in eine andere Bohne scoped, müssen Sie injizieren ein AOP-Proxy anstelle der Bereichs-Bean. Das heißt, Sie müssen ein Proxy-Objekt einfügen, das die gleiche öffentliche Schnittstelle wie das Objekt mit Gültigkeitsbereich bereitstellt, das aber auch das reale Zielobjekt aus dem relevanten Bereich (z. B. eine HTTP-Anforderung) abrufen und Methodenaufrufe an das reale Objekt delegieren kann .

über ThreadLocal:

da nicht von einem lokalen Thread zu verwenden.

Zum Glück - Frühling benutzt einen für Sie. Wenn Sie verstehen, wie ThreadLocal funktioniert - Spring stellt die aktuelle Anforderung in einen lokalen Thread und delegiert an die fadenlokale Instanz, wenn Sie auf httpServletRequest Proxy zugreifen.

+0

Tom, das ist eine gute Antwort. Ist es möglich, dass Spring dies irgendwo dokumentiert hat, wo ich es nachlesen könnte? Es war sehr schwierig, etwas zu finden, das mit der Funktionsweise der Proxyfunktion zusammenhängt.Oh, und ich brauche keinen Zugriff auf die Anfrage von der init() - das war betrügt mich und drückte zwei Fragen in einem :) –

+0

@BrianReindel: Ich Referenz in meiner Antwort auf die Frühlings-Dokumentation enthalten. –

+0

Hallo Thomasz, wird der Code in Antwort funktionieren? Können Sie auch Ihre Meinung zu "http://stackoverflow.com/questions/22923813/set-systems-pro-controlling-and-access-that-in-an-aspect" abgeben? – riship89

Verwandte Themen