2013-02-01 16 views
10

मैं एक वर्ग कि इतने तरह दिखता है:स्प्रिंग एक स्थिर इंजेक्शन (वैश्विक) सिंगलटन

public class Configurator { 
    private static Configurator INSTANCE = null; 

    private int maxRange = 1; 

    // many other properties; each property has a default value 

    private static synchronized Configurator getInstance() { 
     if(INSTANCE == null) 
      return new Configurator(); 

     return INSTANCE; 
    } 

    public static int getMaxRange() { 
     getInstance().maxRange; 
    } 

    public static void setMaxRange(int range) { 
     getInstance().maxRange = range; 
    } 

    // Getters and setters for all properties follow this pattern 
} 

यह एक वैश्विक विन्यास वस्तु एप्लिकेशन स्टार्टअप पर सेट किया जा सकता है, और फिर वर्गों के दर्जनों द्वारा प्रयोग किया जाता है के रूप में कार्य करता है परियोजना भर में:

// Called at app startup to configure everything 
public class AppRunner { 
    Configurator.setMaxRange(30); 
} 

// Example of Configurator being used by another class 
public class WidgetFactory { 
    public void doSomething() { 
     if(Configurator.getMaxRange() < 50) 
      // do A 
     else 
      // do B 
    } 
} 

अब मैं एक स्प्रिंग परियोजना में इस कोड का आयात कर रहा हूँ, और मेरे Sprinig एक्सएमएल (बीन्स) कॉन्फ़िगर करने के लिए कोशिश कर रहा हूँ।

<bean id="configurator" class="com.me.myapp.Configurator" scope="singleton"> 
    <property name="maxRange" value="30"/> 
    <!-- etc., for all properties --> 
</bean> 

इस तरह, जब WidgetFactory#doSomething कार्यान्वित, वसंत पहले से ही होगा Configurator वर्ग भरी हुई है और यह समय से आगे के लिए कॉन्फ़िगर: मेरा अनुमान है कि मैं एक अकेला Configurator सेम की तरह तो (या कुछ इसी तरह) को परिभाषित कर सकता है।

क्या यह मेरे लिए scope="singleton" सेट करना सही है, या इससे कोई फर्क नहीं पड़ता? क्या मैं स्थिर गुणों को सही ढंग से सेट कर रहा हूं? क्या मुझे कुछ और करने की ज़रूरत है या यहां पर विचार करें? अग्रिम में धन्यवाद।

उत्तर

7

सिंगलटन के बीच एक डिजाइन पैटर्न और स्प्रिंग की सिंगलटन सुविधा के रूप में कुछ अंतर हैं। डिज़ाइन पैटर्न के रूप में सिंगलटन यह सुनिश्चित करेगा कि आपके पास प्रति वर्ग लोडर परिभाषित कक्षा का एक ऑब्जेक्ट होगा। इसके विपरीत, वसंत की सिंगलटन सुविधा (और दृष्टिकोण) प्रति वसंत संदर्भ में एक उदाहरण परिभाषित करेगी।

इस मामले में आप अपने getInstance() पद्धति का उपयोग कर सकते हैं स्प्रिंग द्वारा प्रयोग किया जाता करने के लिए किया जा अपनी वस्तु दृष्टान्त हड़पने के लिए:

<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance"> 
</bean> 

वसंत के साथ singleton सेम गुंजाइश डिफ़ॉल्ट है इसलिए आप इसे परिभाषित करने की जरूरत नहीं है।

यदि आप स्प्रिंग बीन के रूप में configurator का उपयोग करना चाहते हैं तो आपको इसे अन्य वस्तुओं में इंजेक्ट करना होगा, getInstance() का उपयोग इसे पकड़ने के लिए नहीं करना चाहिए। तो अन्य वसंत बीन्स में @Autowired का उपयोग करें या xml फ़ाइल के माध्यम से बीन के संदर्भ को परिभाषित करें। यदि आप अन्य कक्षाओं में configurator के उपयोग को पुनर्गठित नहीं करते हैं, तो कोई फर्क नहीं पड़ता, वसंत आपकी कक्षा को तुरंत चालू करेगा, लेकिन आप इसे पहले के रूप में उपयोग करेंगे।

इसके अलावा मैंने देखा कि आपको अपने सिंगलटन को डिजाइन करने में त्रुटि है। आपकी getInstance() विधि सार्वजनिक होनी चाहिए, और अन्य विधियां स्थिर नहीं होनी चाहिए। किसी भी वस्तुओं instantiating बिना

Configurator.getInstance().someMethod() 

इस मामले आप वास्तव में सिर्फ सिंगलटन वर्ग का उपयोग में,: उदाहरण में आप का उपयोग किया है आप इस तरह सिंगलटन का उपयोग करना चाहिए! सिंगलटन डिज़ाइन पैटर्न और इसका उपयोग करने के तरीके के बारे में अधिक जानकारी के लिए wikipedia on Singleton (with Java example) देखें।


नोट: यह जानने और Configurator एक सिंगलटन के रूप में इस्तेमाल करते हैं और उपयोग वसंत के सिंगलटन सुविधा के प्रयास के लायक है। यदि आप करते हैं यह लाभ होगा कि आप

  • getInstance() विधि निकाल सकते हैं
  • अपने निर्माता सार्वजनिक
  • स्प्रिंग एक वस्तु है कि दृष्टांत हैं बनाओ।
+0

धन्यवाद @partlov (+1) - क्या मुझे अपनी 'getInstance()' विधि सार्वजनिक करने की आवश्यकता होगी, या क्या वसंत इस तथ्य को संभाल सकता है कि यह निजी है? –

+0

आपको इसकी आवश्यकता नहीं है (getInstance()) –

1

बीन्स डिफ़ॉल्ट रूप से सिंगलटन हैं। आप वसंत वेबसाइट के माध्यम से यह/अधिक जानकारी पा सकते हैं।

आपको getInstance में एक नया कॉन्फ़िगरेटर तुरंत चालू नहीं करना चाहिए क्योंकि यह वसंत भारित बीन का संदर्भ नहीं देगा और इससे कुछ गंभीर समस्याएं हो सकती हैं। आप इस बीन को तार में रख सकते हैं और फिर इसे अकेला छोड़ सकते हैं, यह शून्य नहीं होगा क्योंकि आपने इसे तार दिया है (और यदि आपका प्रोग्राम प्रारंभ करने में असफल रहा होगा)।

0

हां, यदि आप कुछ वैश्विक चाहते हैं, तो सिंगलटन स्कोप सही विकल्प है। कुछ लायक बातें यहाँ यह उल्लेख कर रहे हैं:

  1. वसंत में डिफ़ॉल्ट गुंजाइश सिंगलटन, तो आप स्पष्ट रूप से सिंगलटन गुंजाइश के रूप में अपने सेम सेट की जरूरत नहीं है है।
  2. वसंत का उपयोग करने के लिए आपको सिंगलटन पैटर्न शैली कोड, जैसे निजी उदाहरण और फैक्ट्री विधियों को लिखने की आवश्यकता नहीं है। ऐसा इसलिए है क्योंकि वसंत गारंटी देगा कि वसंत कंटेनर प्रति केवल एक ही उदाहरण है। यह भी कहना नहीं है, आपकी फैक्ट्री विधि निजी है।
0

वैसे: इस थ्रेड-सुरक्षित नहीं:

if(INSTANCE == null) 
     return new Configurator(); 

    return INSTANCE; 
} 

जबकि इस होगा:

private static Configurator INSTANCE = new Configurator(); 

(उत्सुक प्रारंभ)

private static volatile Singleton _instance = null; 

(Lazy आरंभीकरण अस्थिर कीवर्ड के साथ)

जावा को मेमोरी आवंटित करने और उदाहरण बनाने के तरीके से करना होगा। यह परमाणु नहीं है, लेकिन दो चरणों में किया गया है और थ्रेड शेड्यूलर द्वारा हस्तक्षेप किया जा सकता है।

http://regrecall.blogspot.de/2012/05/java-singleton-pattern-thread-safe.html भी देखें।

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