2012-05-10 14 views
9

के लिए पहलू थ्रेड सुरक्षा मैं स्प्रिंग 3 एओपी का उपयोग कर रहा हूं, और मेरे पास एक पहलू है जिसके लिए HttpServletRequest तक पहुंच की आवश्यकता है। यह इस तरह दिखता है:स्प्रिंग एओपी और एक ऑटोवायर HTTPServletRequest बीन

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

और इस तरह कॉन्फ़िगर किया गया है:

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

init विधि केवल आईओसी कंटेनर प्रति एक बार कहा जाता है, भले ही यह एक पहलू है, और httpServletRequest धागा सुरक्षित है ? यदि ऐसा नहीं है, तो सलाह के निष्पादन के दौरान इसे प्राप्त करने का सबसे अच्छा तरीका क्या है और क्या यह धागा सुरक्षित है? यदि संभव हो तो मैं थ्रेड स्थानीय का उपयोग न करना पसंद करता हूं।

उत्तर

16

init विधि केवल एक बार आईओसी कंटेनर

प्रति यह एक बार हर सेम उदाहरण प्रति कहा जाता है कहा जाता है। यदि बीन में सिंगलटन स्कोप होता है (जो पहलुओं के लिए भी डिफ़ॉल्ट मामला है), इसे केवल एक बार बुलाया जाएगा। हालांकि init() विधि के अंदर आपको httpServletRequest तक पहुंच नहीं होगी - अभी तक कोई अनुरोध नहीं है!

httpServletRequest सुरक्षित

धागा यह लेकिन चिंता मत करो नहीं है। यह वास्तव में ऐसा लगता है की तुलना में अधिक जटिल है। आप एक सिंगलटन ऑब्जेक्ट में HTTP सर्वलेट अनुरोध इंजेक्शन कर रहे हैं (और जाहिर है कि एक ही समय में कई अनुरोध उपलब्ध हो सकते हैं)। कौन सा इंजेक्शन दिया जाता है? उनमें से कोई नहीं (सब?)! वसंत कुछ परिष्कृत प्रॉक्सी बनाता है (जिसे स्कॉप्ड प्रॉक्सी कहा जाता है) और हर बार जब आप httpServletRequest इंजेक्शन के तरीकों तक पहुंचते हैं तो यह उन्हें वर्तमान (थ्रेड) अनुरोध पर भेजता है। इस तरह आप कई पहलुओं में अपने पहलुओं को सुरक्षित रूप से चला सकते हैं - प्रत्येक एक अलग शारीरिक अनुरोध पर काम करेगा।

इस पूरे व्यवहार 4.5.4.5 Scoped beans as dependencies में महान विवरण में वर्णित है:

[...] आप इंजेक्षन (उदाहरण के लिए) एक HTTP अनुरोध एक और सेम में सेम scoped करना चाहते हैं, तो आप इंजेक्षन चाहिए एक स्कोप्ड बीन के स्थान पर एओपी प्रॉक्सी। यही है, आपको एक प्रॉक्सी ऑब्जेक्ट इंजेक्ट करने की आवश्यकता है जो स्कॉप्ड ऑब्जेक्ट के समान सार्वजनिक इंटरफ़ेस को उजागर करता है लेकिन यह वास्तविक दायरे से वास्तविक, लक्षित ऑब्जेक्ट को भी पुनर्प्राप्त कर सकता है (उदाहरण के लिए, एक HTTP अनुरोध) और असली ऑब्जेक्ट पर प्रतिनिधि विधि कॉल ।

बारे ThreadLocal:

मैं एक धागा स्थानीय उपयोग नहीं करना चाहते।

सौभाग्य से - वसंत आपके लिए एक का उपयोग कर रहा है। यदि आप समझते हैं कि ThreadLocal काम करता है - वसंत httpServletRequest प्रॉक्सी तक पहुंचने पर स्प्रिंग वर्तमान अनुरोध को थ्रेड स्थानीय और प्रतिनिधि को थ्रेड-स्थानीय उदाहरण में रखता है।

+0

टॉम, यह एक अच्छा जवाब है। क्या यह संभव है कि स्प्रिंग ने कहीं ऐसा दस्तावेज किया होगा जिसे मैं पढ़ सकता हूं? प्रॉक्सी वास्तव में कैसे काम करता है उससे संबंधित कुछ भी ढूंढना बहुत मुश्किल था।ओह, और मुझे init() के भीतर से अनुरोध तक पहुंच की आवश्यकता नहीं है - वह मुझे धोखा दे रहा था और दो प्रश्नों को निचोड़ रहा था :) –

+0

@BrianReindel: मैंने अपने उत्तर में स्प्रिंग दस्तावेज़ों का संदर्भ शामिल किया। –

+0

हाय थॉमस, क्या उत्तर में कोड कोड होगा? क्या आप अपनी राय भी दे सकते हैं "http://stackoverflow.com/questions/22923813/set-systems-property-in-controller-and-access-that-in-an-aspect" – riship89

संबंधित मुद्दे