2011-10-01 15 views
84

मैं अपने नियंत्रक में एक एनोटेटेड प्रोटोटाइप बीन का उपयोग करना चाहता हूं। लेकिन वसंत इसके बजाय एक सिंगलटन बीन बना रहा है। यहाँ उस के लिए कोड है:@ स्कोप ("प्रोटोटाइप") बीन स्कोप नया बीन नहीं बना रहा

@Component 
@Scope("prototype") 
public class LoginAction { 

    private int counter; 

    public LoginAction(){ 
    System.out.println(" counter is:" + counter); 
    } 
    public String getStr() { 
    return " counter is:"+(++counter); 
    } 
} 

नियंत्रक कोड:

@Controller 
public class HomeController { 
    @Autowired 
    private LoginAction loginAction; 

    @RequestMapping(value="/view", method=RequestMethod.GET) 
    public ModelAndView display(HttpServletRequest req){ 
     ModelAndView mav = new ModelAndView("home"); 
     mav.addObject("loginAction", loginAction); 
     return mav; 
    } 

    public void setLoginAction(LoginAction loginAction) { 
     this.loginAction = loginAction; 
    } 

    public LoginAction getLoginAction() { 
     return loginAction; 
    } 
    } 

वेग टेम्पलेट:

<context:annotation-config /> 
    <context:component-scan base-package="com.springheat" /> 
    <mvc:annotation-driven /> 
:

LoginAction counter: ${loginAction.str} 

स्प्रिंग config.xml घटक स्कैनिंग सक्षम किया गया

मुझे हर बार एक बढ़ी हुई गिनती मिल रही है। यह पता नहीं लगा सकता कि मैं गलत कहां जा रहा हूं!

अद्यतन

suggested by @gkamal रूप में, मैं HomeControllerwebApplicationContext -aware बना दिया है और यह समस्या हल हो।

अद्यतन कोड:

@Controller 
public class HomeController { 

    @Autowired 
    private WebApplicationContext context; 

    @RequestMapping(value="/view", method=RequestMethod.GET) 
    public ModelAndView display(HttpServletRequest req){ 
     ModelAndView mav = new ModelAndView("home"); 
     mav.addObject("loginAction", getLoginAction()); 
     return mav; 
    } 

    public LoginAction getLoginAction() { 
     return (LoginAction) context.getBean("loginAction"); 
    } 
} 
+7

काश मैं में सही जवाब लागू करने के लिए आप वोट दें दोगुनी हो सकती है दूसरों के लिए वास्तविक अंतर देखने के लिए आपका कोड –

उत्तर

104

स्कोप प्रोटोटाइप मतलब यह है कि हर बार जब आप एक उदाहरण यह एक नया उदाहरण बना सकते हैं और है कि के लिए एक संदर्भ दे देंगे के लिए वसंत (getBean या निर्भरता इंजेक्शन) पूछते हैं।

आपके उदाहरण में लॉगिनएक्शन का एक नया उदाहरण बनाया गया है और आपके होमकंट्रोलर में इंजेक्शन दिया गया है। यदि आपके पास एक और नियंत्रक है जिसमें आप लॉग इनएक्शन इंजेक्ट करते हैं तो आपको एक अलग उदाहरण मिलेगा।

यदि आप प्रत्येक कॉल के लिए एक अलग उदाहरण चाहते हैं - तो आपको प्रत्येक बार GetBean को कॉल करने की आवश्यकता है - एक सिंगलटन बीन में इंजेक्शन करने से उसे प्राप्त नहीं होगा।

+5

मैंने नियंत्रक एप्लिकेशनकॉन्टेक्स्टवेयर बनाया और मुझे बीन मिला और मुझे हर बार ताजा बीन मिल रहा है। धन्यवाद दोस्तों!!! – tintin

+0

बीन के 'प्रोटोटाइप' दायरे के बजाय 'अनुरोध' दायरा होने पर यह कैसे काम करता है। क्या आपको अभी भी 'context.getBean (..)' के साथ बीन पुनर्प्राप्त करने की आवश्यकता होगी? –

+0

या स्कोप्ड प्रॉक्सी का उपयोग करें, यानी @ स्कोप (मान = "प्रोटोटाइप", प्रॉक्सीमोड = स्कॉप्डप्रोक्सी मोड। TARGET_CLASS) – svenmeier

12

सिर्फ इसलिए कि नियंत्रक में इंजेक्शन वाले बीन प्रोटोटाइप-स्कोप्ड का मतलब नियंत्रक नहीं है!

2

ApplicationContextAware का उपयोग करके आप वसंत (जो कोई मुद्दा हो या नहीं हो) का उपयोग कर रहा है। मैं LoginActionFactory में गुजरने की अनुशंसा करता हूं, जिसे आप प्रत्येक बार एक LoginAction के नए उदाहरण के लिए पूछ सकते हैं।

+1

पहले से ही स्प्रिंग-विशिष्ट एनोटेशन हैं; ऐसा लगता है कि यह चिंता का विषय नहीं है। –

+1

@ डेव, अच्छा बिंदु। कुछ डीआई सामान (जेएसआर 311) के लिए विकल्प हैं, लेकिन इस उदाहरण में वसंत निर्भर सब कुछ से खुद को छुटकारा पाना मुश्किल हो सकता है। मुझे लगता है कि मैं वास्तव में केवल 'फैक्ट्री-विधि' की वकालत कर रहा हूं ... –

+1

+1 नियंत्रक में सिंगलटन 'लॉग इनएक्शन फैक्ट्री' इंजेक्शन के लिए +1, लेकिन 'फैक्ट्री-विधि' ऐसा प्रतीत नहीं होता है कि यह इस मुद्दे को हल करेगा कारखाने के माध्यम से एक और वसंत बीन बनाता है। सिंगलटन नियंत्रक में उस बीन को इंजेक्शन देने से समस्या का समाधान नहीं होगा। –

-6

अपने नियंत्रक भी @Scope ("प्रोटोटाइप") की जरूरत है defind

इस तरह:

@Controller 
@Scope("prototype") 
public class HomeController { 
..... 
..... 
..... 

} 
+0

आपको क्यों लगता है कि नियंत्रक को प्रोटोटाइप भी होना चाहिए? –

+5

यह सिर्फ सादा गलत है। –

7

@controller एक सिंगलटन वस्तु है, और अगर एक सिंगलटन वर्ग के लिए एक प्रोटोटाइप सेम इंजेक्षन कर देगा प्रोटोटाइप बीन सिंगलटन के रूप में भी जब तक आप लुकअप-विधि प्रॉपर्टी का उपयोग करके निर्दिष्ट नहीं करते हैं जो वास्तव में आपके द्वारा किए गए प्रत्येक कॉल के लिए प्रोटोटाइप बीन का एक नया उदाहरण बनाते हैं।

3

उपयोग अनुरोध गुंजाइश @Scope("request") प्रत्येक अनुरोध के लिए सेम प्राप्त करने के लिए, या @Scope("session") प्रत्येक सत्र 'उपयोगकर्ता

2

nicholas.hauschild ने उल्लेख किया स्प्रिंग संदर्भ इंजेक्शन लगाने के एक अच्छा विचार नहीं है के लिए सेम मिलता है। आपके मामले में, @ स्कोप ("अनुरोध") इसे ठीक करने के लिए पर्याप्त है। लेकिन मान लें कि आपको नियंत्रक विधि में LoginAction के कई उदाहरणों की आवश्यकता है।(Spring 4 समाधान) इस मामले में, मैं प्रदायक की सेम बनाने के लिए सिफारिश करेंगे:

@Bean 
    public Supplier<LoginAction> loginActionSupplier(LoginAction loginAction){ 
     return() -> loginAction; 
    } 

फिर नियंत्रक को इसकी सुई:

@Controller 
public class HomeController { 
    @Autowired 
    private Supplier<LoginAction> loginActionSupplier; 
संबंधित मुद्दे