2015-11-03 8 views
7

मैं जावा वेबपैप में एक उचित गुण प्रबंधन रणनीति बनाना चाहता हूं जो कि Google guice पर डीआई फ्रेमवर्क के रूप में रहता है।Google गिइस प्रॉपर्टीज मैनेजमेंट

मैं निम्नलिखित 3 आवश्यकताओं का जवाब देने के लिए एक तंत्र करना चाहते हैं:

  • मैं चाहूँगा guice (@Named) का उपयोग गुण इंजेक्षन करने में सक्षम होना
  • मैं गुण उपयोग करने में सक्षम होना चाहते हैं एक स्थिर तरीके से
  • तंत्र को गुणों के प्राथमिकता का समर्थन करना चाहिए, जिसका अर्थ है कि एक संपत्ति को एक निश्चित मूल्य के साथ तैनात युद्ध में लपेटा जा सकता है लेकिन यह लक्ष्य प्रणाली स्तर या स्थानीय फ़ाइल सिस्टम (लक्ष्य मशीन के) में भी अनावश्यक हो सकता है मैं तैनात करता हूं), इस तरह के मामले में युद्ध में मूल्य मूल्य वें द्वारा ओवरराइड किया जाएगा लक्ष्य मशीन में मौजूद है।

मेरा मानना ​​है कि यह एक मानक आवश्यकता है। अब, गाइड मानक बाइंडर का उपयोग करके मैं आसानी से पहली आवश्यकता प्राप्त कर सकता हूं लेकिन अन्य दो नहीं।

  • Wraps और बाध्यकारी (उन है कि गुण बांधता है) उदाहरण के लिए guice के तरीकों को उजागर करता है:

public static void bindString(AnnotatedBindingBuilder<String> binder, String property, String defaultValue) { binder.annotatedWith(Names.named(property)).toInstance(getProperty(property, defaultValue)); }

कहाँ अन्य दो प्राप्त करने के लिए मैं अपने ही वर्ग है जो निम्न करता बनाया getProperty विधि जानता है कि मेरे गुणों को कैसे प्रबंधित करें (युद्ध या सिस्टम स्तर से मूल्य प्राप्त करें) और गुणों को स्थिर रूप से भी प्रकट करता है।

तो मूल रूप से जब तक मैं इस उपयोगिता का उपयोग कर रहा हूं, जिसे मैंने गुणों के लिए बनाया है, मैं अच्छा हूं, इसमें मेरी सभी आवश्यकताओं को शामिल किया गया है, लेकिन एक बार जब मैं मानक गेज बाइंडिंग का उपयोग करता हूं तो मैं दूसरी और तीसरी आवश्यकता खो रहा हूं।

क्या गुइस बाइंडिंग को ओवरराइड करने और उन सभी 3 आवश्यकताओं को प्राप्त करने का कोई तरीका है?

एक बार मेरे पास वसंत आधारित ऐप में एक ही चुनौती थी और यह बहुत आसान था। मैं निम्नलिखित विधि के साथ ApplicationContextInitializer कार्यान्वित:

@Override public void initialize(ConfigurableWebApplicationContext ctx) { PropertySource<Map<String, Object>> localProps = null; try { localProps = new ResourcePropertySource(new ClassPathResource(LOCAL_PROPERTIES_FILE_NAME)); } catch (IOException e) { LOG.fatal("Could not load local properties from classpath " + LOCAL_PROPERTIES_FILE_NAME); return; } LOG.info("Loaded configuration from classpath local file " + LOCAL_PROPERTIES_FILE_NAME); ctx.getEnvironment().getPropertySources().addFirst(localProps); }

तो यह मुझे मेरे पर्यावरण को सर्वोच्च प्राथमिकता के साथ स्थानीय प्रॉपर्टी जोड़ने के लिए एक मार्ग प्रशस्त किया। युद्ध गुणों के साथ ओवरलैप के मामले में स्थानीय लोगों की उच्च प्राथमिकता थी। इसके अलावा मैंने अपने पर्यावरण को स्थिर रूप से उजागर किया, इसलिए मेरे पास मेरी संपत्तियों के लिए स्थिर पहुंच है (उन सेवाओं के लिए जो कंटेनर द्वारा प्रबंधित नहीं हैं, विरासत अधिकतर)।

मैं इसे गाइड के साथ कैसे प्राप्त कर सकता हूं?

+0

आपका क्या मतलब है, कि आप एक स्थिर तरीके से गुण का उपयोग करना चाहते हैं? क्या इसका मतलब यह है कि आपके पास उपयोग-मामले हैं जहां आप किसी विशेष संपत्ति तक पहुंचना चाहते हैं, लेकिन आप तब तक नहीं जानते जब तक कि आप जिस संपत्ति को एक्सेस करना चाहते हैं? –

+0

मैं कुछ का उपयोग कर किसी संपत्ति का उपयोग करने में सक्षम होना चाहूंगा: SomeClass.getProperty ("my.property"); यह कक्षाओं के लिए उपयोगी होना चाहिए जो कि गुइस (विरासत आमतौर पर) द्वारा प्रबंधित नहीं होते हैं और अभी भी मेरी गुणों तक पहुंच की आवश्यकता है – forhas

उत्तर

1

दुर्भाग्य से, मुझे नहीं लगता कि आपको ऐसा कुछ भी मिल जाएगा जो आपको वास्तव में स्वच्छ और संतोषजनक कार्यान्वयन प्रदान करता है। विशेष रूप से, मुझे नहीं लगता कि आपको कुछ भी मिलेगा जो आपको कम से कम भागों को लागू किए बिना बिल्कुल वही देता है जो आप चाहते हैं।

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

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

public class InjectorFactory { 
    private static Injector injector = null; 
    public static synchronized Injector getOrCreateInjector() { 
     if(injector == null) { 
      injector = Guice.createInjector(new AbstractModule() { 
       @Override 
       protected void configure() { 
        Properties properties1 = createProperties("file1.properties"); 
        Properties properties2 = createProperties("file2.properties"); 
        Set<Object> propertyNames = new HashSet<Object>(); 
        propertyNames.addAll(properties1.keySet()); 
        propertyNames.addAll(properties2.keySet()); 

        for (Object object : propertyNames) { 
         String propertyName = (String) object; 
         bind(String.class).annotatedWith(Names.named(propertyName)).toProvider(new StringProvider(properties1, properties2, propertyName)); 
        } 
       } 

       private Properties createProperties(String propertyFileName) { 
        try { 
         InputStream stream = InjectorFactory.class.getResourceAsStream(propertyFileName); 
         try { 
          Properties properties = new Properties(); 
          properties.load(stream); 
          return properties; 
         } finally { 
          stream.close(); 
         } 

        } catch (IOException exception) { 
         throw new RuntimeException("Could not load properties file"); 
        } 
       } 
      }); 
     } 
     return injector; 
    } 

    public static String getProperty(String propertyName) { 
     return getOrCreateInjector().getInstance(Key.get(String.class, Names.named(propertyName))); 
    } 

} 

को देखते हुए उपरोक्त कोड और file1.properties:

property1=Property1Value 
property2=Property2Value 

और file.properties:

:

property2=IncorrectProperty2Value 
property3=Property3Value 
प्रदाता

public class StringProvider implements Provider<String> { 
    private Properties properties1; 
    private Properties properties2; 
    private String propertyName; 
    public StringProvider(Properties properties1, Properties properties2, 
      String propertyName) { 
     this.properties1 = properties1; 
     this.properties2 = properties2; 
     this.propertyName = propertyName; 
    } 
    public String get() { 
     if(properties1.containsKey(propertyName)) { 
      return properties1.getProperty(propertyName); 
     } 
     return properties2.getProperty(propertyName); 
    } 
} 

निम्नलिखित उपयोग के साथ

public class InjectorFactoryTest { 
    public static void main(String ... parameters) { 
     System.out.println(InjectorFactory.getProperty("property1")); 
     System.out.println(InjectorFactory.getProperty("property2")); 
     System.out.println(InjectorFactory.getProperty("property3")); 
    } 
} 

आउटपुट:

Property1Value 
Property2Value 
Property3Value 
+0

अच्छा, लेकिन अभी भी एक नुकसान हुआ - कोई भी इस कारखाने के उपयोग को लागू नहीं करता है। उदाहरण के लिए, अगर कोई नया मॉडल बनाने का फैसला करता है लेकिन इस फैक्ट्री का उपयोग नहीं करता है तो मैं कारखाने के गुणों के लिए गुइस प्रबंधित गुणों के बीच एक अंतर के साथ समाप्त हो सकता हूं, क्या मैं सही हूँ? मैं मानता हूं कि जब तक हर कोई मॉडल निर्माण के लिए कारखाने का उपयोग करता है, यह समाधान प्रदान करेगा, लेकिन यह मेरे लिए पर्याप्त नहीं है (इस समय मेरे पास एक समान समाधान है, बस थोड़ा सा सरल :)) – forhas

+0

हां। आम तौर पर, यदि कोई "नया" उपयोग करना चाहता है तो कोई भी नई ऑब्जेक्ट्स बना सकता है या नहीं तो वे अपने स्वयं के इंजेक्टर बना सकते हैं यदि वे मॉड्यूल की अपनी सूची इकट्ठा करना चाहते हैं। जब तक आप अपनी जेवीएम नीतियों को प्रबंधित करना शुरू नहीं करना चाहते हैं और कौन से वर्गों को अन्य वर्गों तक पहुंचने की अनुमति है, तो वास्तव में इसे प्रतिबंधित करने का कोई तरीका नहीं है। लक्ष्य, फिर, लोगों को "सही तरीके से" करने के लिए जितना संभव हो सके उतना आसान बनाना है। और जैसा कि मैंने पहले कहा था, मुझे लगता है कि यह संभावना नहीं है कि आपको एक समाधान मिलेगा जो बहुत संतोषजनक महसूस करता है। –

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