2011-10-03 6 views
7

Guice के बारे में एक सवाल reinjection। मैं अभी भी इसे सीख रहा हूं, लेकिन मैं मूलभूत सिद्धांतों को समझ सकता हूं।Guice क्रम निर्भरता मापदंडों

यह सवाल पहले से ही नेट पर एक दो बार पूछा गया था, लेकिन कभी नहीं एक ठोस जवाब (कोई नहीं है कि मैं मिल सकता है) के साथ।

मैं चित्र पर की तरह एक स्थिति है (एक समान उदाहरण नेट पर somewere था) कहो।

enter image description here

public class Dog {} 

public class Walk implements Walkable { 
    private final Dog dog; 
    private final boolean leash; 

    @Inject 
    public Walk(Dog dog, @Assisted boolean leash) { 
     this.dog = dog; 
     this.leash = leash; 
    } 

    public void go() { 
    } 
} 

public interface Walkable { 
    void go(); 
} 

public interface WalkFactory { 
    Walk create(boolean leash); 
} 

public class AssistedMain { 
    public static void main(String[] args) { 
     Injector i = Guice.createInjector(new AbstractModule() { 
      protected void configure() { 

       install(new FactoryModuleBuilder(). 
         implement(Walkable.class, Walk.class). 
         build(WalkFactory.class)); 
      } 
     }); 

     Walk walk = i.getInstance(WalkFactory.class).create(true); 
    } 
} 

बस इतना ही बढ़िया है। लेकिन सवाल यह है कि - क्या मैं, किसी भी तरह, इस निर्भरता पर भरोसा रखने वाले वर्गों पर उपयोग किए जाने वाले "कंटेनर" (इंजेक्टर) को उस ऑब्जेक्ट उदाहरण को पुन: पेश कर सकता हूं।

तो, एक interface Person, class PersonImpl जोड़ सकते हैं।

enter image description here

नए वर्गों स्रोत हैं:

public interface Person { 
    void walkDog(); 
} 

public class PersonImpl implements Person { 
    private Walkable walkable; 

    @Inject 
    public PersonImpl(Walkable walkable) { 
     this.walkable = walkable; 
    } 

    public void setWalkable(Walkable walkable) { 
     this.walkable = walkable; 
    } 

    public void walkDog() { 
     walkable.go(); 
    } 
} 

तो, सवाल है - मैं कर रहा हूँ, किसी भी तरह वास्तव में जोड़ा वस्तु में इस विशेष उदाहरण इंजेक्षन करने में सक्षम। यह एक साधारण उदाहरण है, लेकिन हम मान सकते हैं कि इस के नीचे कक्षाओं के 10 स्तर हैं।

समाधान मैंने पाया बहुत लचीला नहीं है। कुछ की तरह:

Injector i = Guice.createInjector(new SimpleModule(false, dog));

और फिर ठोस उदाहरण के लिए बाध्य। यह बहुत गतिशील नहीं है। असल में, हर बार मुझे एक अलग रनटाइम/गतिशील पैरामीटर की आवश्यकता होती है, मुझे इंजेक्टर को फिर से बनाना होगा।

Provider<T> अच्छा है, FactoryModuleBuilder मदद करता है, लेकिन मैं वस्तुओं को वापस कैसे इंजेक्ट कर सकता हूं?

इस समस्या का समाधान और अधिक गतिशील हैं?

धन्यवाद।

उत्तर

4

एमपीियरस - सहमत हुए। मैं जिस तरह से समस्या को कल्पना करता हूं उसे समझाने की कोशिश करता हूं (यदि आप गलत हैं तो आप मुझे सही कर सकते हैं)।

मूल रूप से "सेवा लोकेटर" पैटर्न से व्युत्पन्न होने के नाते, विचार यह है कि यह सेवाओं से अधिक प्रबंधन कर सकता है कम से कम कहने के लिए आशावादी है।

हम सेवा और डेटा वर्गों में आवेदन विभाजित कर सकते हैं, या आप कह सकते हैं कि हम आवेदन और बुनियादी ढांचे कोड है - "निर्भरता इंजेक्शन", एक महान किताब।

तो, मूल रूप से, निर्भरता इंजेक्शन, और निर्भरता इंजेक्शन ढांचे सामान्य रूप से महान हैं। आधारभूत संरचना, या "सेवा" कोड को हल करने के लिए।

किसी भी गतिशील (क्रम) पैरामीटर कंटेनर/इंजेक्टर में इंजेक्ट किया जा रहा है मूल रूप से हैं वस्तु ग्राफ अंत के लिए मजबूर।

enter image description here

EmailMessage एक क्रम पैरामीटर है:

उदाहरण के लिए, हम folowing डिजाइन की है। इसे कंटेनर/इंजेक्टर के बाहर ईमेल सेवा में "इंजेक्शन" किया जा सकता है, लेकिन यह ऑब्जेक्ट ग्राफ़ को समाप्त करता है। अगर हम ईमेल डिस्प्ले में ईमेलमेसेज इंजेक्शन देने के बाद ईमेल डिस्प्लेचर से अनुरोध करना चाहते हैं (यानी, मैं इंजेक्टर के बाहर किया गया है), तो हम अब इंजेक्टर से ईमेल डिस्प्लेचर नहीं ला सकते हैं।

फिर, आप अपने मॉडल को फिर से डिजाइन कर सकते हैं ताकि यह गतिशील मानकों के कंटेनर/इंजेक्टर अवधारणा में "फिट हो"।

enter image description here

लेकिन तब फिर से, आप डिजाइन के लिए मजबूर किया, और अचानक, EmailDispatcher भी कई ज़िम्मेदारियां है। इसका उपयोग ऐसे संदर्भ में किया जा सकता है, जहां आपके पास कई बुनियादी ढांचे वर्ग नहीं हैं।

enter image description here

और जब आप एक डिजाइन है जैसे आप तीसरा उदाहरण चित्र में है, तो आप (EmailDispatcher के स्तर से नीचे है और न ही कोई हो) आप एक NextService3 उदाहरण लाने के लिए इंजेक्टर/कंटेनर का उपयोग नहीं कर सकते हैं।

समस्या होने पर - यदि आपके पास कोई गतिशील (रनटाइम) पैरामीटर है, तो आप केवल कक्षा के ऊपर कक्षाओं के लिए निर्भरता इंजेक्शन का उपयोग कर सकते हैं जिसके लिए गतिशील पैरामीटर की आवश्यकता होती है, आप नीचे दिए गए वर्गों को भूल सकते हैं।

पुhew।

सही?

+0

मुझे समझ में आता है। – mpierce

1

समस्या का एक हिस्सा इस बात पर निर्भर करता है कि आप कैसे हल कर रहे हैं कि 'झूठी' चीज है जिसे आप पट्टा क्षेत्र के लिए सेट करना चाहते हैं। क्या यह कॉन्फ़िगरेशन डेटा से आता है या क्या?

एक प्रदाता विधि सहायक हो सकता है ...

class FooModule extends AbstractModule { 
... 
    @Provides 
    Walkable getWalkable(Dog dog) { 
     boolean leash = getBooleanFromSomewhere(); 
     return new Walk(dog, leash); 
    } 
} 

यदि आप जहां कि बूलियन से आ रही है स्पष्ट कर सकते हैं, यह मुझे समझने के लिए दृष्टिकोण की किस प्रकार लागू होता है में मदद करेंगे।

+0

पट्टा आवेदन में एक गतिशील पैरामीटर है। आइए कहें कि यह पैरामीटर एप्लिकेशन में उपयोगकर्ता द्वारा प्रदान किया गया है (एक पट्टा चेकबॉक्स है :))। उपयोगकर्ता उस चेकबॉक्स को चेक और अनचेक कर सकता है और किसी व्यक्ति को पट्टा के साथ या उसके बिना कुत्ते को चलने की उम्मीद करता है। "समस्या" यह है कि वह पैरामीटर गतिशील है, और "कंटेनर" में "पुनर्जन्म" की आवश्यकता होगी, इसलिए "आधारभूत संरचना" ऑब्जेक्ट ग्राफ़ उस पैरामीटर के अनुसार वस्तुओं को instanciate कर सकते हैं। यह एक साधारण उदाहरण है, कहें कि आपके पास 30 उपयोगकर्ता हैं, और आप लॉगिन के आधार पर प्रत्येक के लिए UserTransaction प्राप्त करना चाहते हैं। – pfh

+0

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

1

आप custom scopes का उपयोग कर सकते हैं, जैसे कि guice servlets का उपयोग करते समय। इस तरह आप अपना उदाहरण बना सकते हैं, और उसके बाद इंजेक्टर में बीज बना सकते हैं।

+0

एक अच्छा विचार है, लेकिन वास्तव में समस्या को हल नहीं करता है। समस्या "कार्यान्वयन के लिए एनोटेशन बाध्यकारी" में गतिशील पुनर्मिलन है, उदाहरण इंजेक्टर के भीतर से उदाहरण को instanciates। प्रारंभिक होने से पहले एक वस्तु को गुजरने के साथ एक ही कार्यक्षमता को प्राप्त किया जा सकता है (जो और भी गतिशील होगा)। बिंदु यह है कि कस्टम स्कॉप्स उपयोगी हैं, लेकिन इस संदर्भ में नहीं - मुझे अभी भी इंजेक्टर में एक अनावश्यकता है, जिसका अर्थ है कि यह एक स्थिर रूप से प्रारंभिक कंटेनर है, वास्तव में मुझे वस्तु इंजेक्शन पर कोई लचीलापन नहीं दे रहा है। – pfh