2011-10-03 78 views
7

關於Guice的問題。我仍然在學習它,但我可以理解基礎知識。Guice運行時依賴關係參數回注

這個問題已經在網上問了幾次,但從來沒有一個具體的答案(我找不到)。

說我有一個像圖片的情況(一個類似的例子有些在網上)。

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

MPierce - 同意。我試圖解釋我看到問題的方式(如果我錯了,你可以糾正我)。

作爲源自「服務定位器」模式的獨創性,它可以管理多種服務的想法至少可以說是樂觀的。

我們可以在應用程序分成服務和數據類,或者你可以說,我們有應用和基礎架構代碼 - 「依賴注入」,一個偉大的書。

因此,從根本上說,依賴注入和依賴注入框架通常都很好。 用於解決基礎設施或「服務」代碼。

任何注入容器/注入器的動態(運行時)參數基本上都是,迫使您結束對象圖

例如,我們有如下因素設計:

enter image description here

EmailMessage是一個運行參數。它可以被注入到容器/注入器外的電子郵件服務中,但它會結束對象圖。 如果我們想要請求EmailDispatcher,在我們將EmailMessage注入EmailService(也就是我重複的,在注入器之外完成)後,我們不能再從注入器中獲取EmailDispatcher。

然後,您可以重新設計您的模型,使其適合動態參數的容器/注射器概念。

enter image description here

但話又說回來,你逼的設計,突然,EmailDispatcher有太多responsibilites。它可以用在這樣的環境中,你沒有很多的基礎設施類。

enter image description here

而當你有一個設計就像你在第三個例子畫面有,你不能使用注射器/容器NextService3實例把你接(或任何低於EmailDispatcher的水平)。

問題是 - 如果您有任何動態(運行時)參數,只能對需要動態參數的類上方的類使用依賴項注入,則可以忘記下面的類。

Phew。

對不起?

+0

對我有意義。 – mpierce

1

問題的一部分取決於你如何解決'假'是你想要爲皮帶領域設置的東西。這是來自配置數據還是什麼?

提供者的方法可能會有所幫助......

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

如果你能澄清如該布爾是從哪裏來的,它會幫助我瞭解什麼類型的方法是適用的。

+0

皮帶是應用程序中的一些動態參數。可以說,這個參數是由用戶提供的,有些在應用程序中(有一個皮帶複選框:))。用戶可以選中並取消選中該複選框,並期望人員在帶或不帶皮帶的情況下行走狗。 「問題」是該參數是動態的,並且需要「回注」到「容器」中,因此「基礎結構」對象圖可以根據該參數實例化對象。這是一個簡單的例子,假設您有30個用戶,並且您希望爲每個用戶獲取UserTransaction,具體取決於登錄。 – pfh

+0

我明白了。那麼,注射可能不是正確的工具。當定義注入的參數由用戶數據驅動時,注入往往很難。 (唉,我不能在註釋中放一個換行符)你可以嘗試使用request-scoped注入,注入的東西取決於你通過檢查已認證的用戶來確定的參數,或者重構你的API以允許'leash'作爲方法參數而不是對象中的字段提供。我不知道你想要的答案,我意識到,但我認爲你正在擴大IoC做得很好的限制。 – mpierce

1

您可以使用custom scopes,就像使用guice servlet時一樣。這樣你可以創建你的實例,然後在注入器中播種它。

+0

一個好主意,但並不真正解決問題。問題在於動態回注,在「將註釋綁定到實現」中,該示例在注入器中實例化了實例。在初始化之前將對象傳遞給guice可以實現相同的功能(這會更加動態)。關鍵是,自定義範圍是有用的,但不是在這種情況下 - 我仍然有一個instanciation在注射器,這意味着它是一個靜態初始化的容器,並沒有真正給我任何靈活的對象注入。 – pfh