2011-03-16 83 views
1

我是相當新的吉斯所以希望這不是一個明顯的問題...注入實例化無法控制的類的最佳方法?

我負責的一個框架,它動態地實例化我的應用程序的一個類(我們稱之爲C)使用反射,所以我無法控制它的實例化。此外,在框架實施後,我無法輕易訪問新創建的C。下面是C會是什麼樣子:

 
    public class C implements I { 

     public C() { 
      // this ctor is invoked by the framework so can't use DI here? 
     }   

     public void initialize() { 
      // this is a post instantiation hook which the f/w will invoke 
     } 

     private void m() { 
      Dependency d = Dependency.getInstance(); 
      d.doSmth(); 
     } 
    } 

我想C使用DI收購Dependency。這裏Dependency顯然是單身人士,但這通常不一定是這種情況。

我想出了兩種可能的解決方案,無論是它的感覺很整潔,所以我認爲我會問專家:

  1. 靜態注入。我很努力地看到,這是如何大大改善服務定位器反模式 - 雖然我最終會得到非最終的靜態字段,可以在外部操縱...嗯。

  2. 該框架支持C的掛鉤以在實例化後自行初始化(上面示出的initialize()方法)。這個方法可以使用setter注入來自我注入新創建的實例。

隨着2,我想這意味着更多的外部可變性,但至少暴露了依賴多一點明確的東西像單元測試。麻煩的是:在那種情況下,我怎樣才能使用Guice Injector(依靠另一個服務定位器)?我也讀過(並且傾向於認同),明確提到整個應用代碼中的Injector是可疑的做法。

您的洞察力將非常感激。

非常感謝,
基督教

回答

2

你可以嘗試靜態注入到供應商C.靜態注入更多的尷尬測試。但是提供者可以讓Guice熱切地驗證你的依賴關係,同時也可以懶惰地創建它們。

public class C implements I { 
    @Inject static Provider<Dep1> dep1Provider; 
    @Inject static Provider<Dep2> dep2Provider; 

    ... 

    public void initialize() { 
    Dep1 dep1 = dep1Provider.get(); 
    Dep2 dep2 = dep2Provider.get(); 
    ... 
    } 
} 
+0

謝謝傑西,這聽起來和我上面的選項1類似;儘管我認爲'提供者'的使用確實使得這種模式更具普遍性。 – sxc731 2011-03-21 17:54:15

1

如果您提供的靜態變量和靜態存取方法,你的吉斯噴油器就可以解決這樣的:

public class C implements I { 

    public C() { 
     // this ctor is invoked by the framework, you can't do injection here. 
    }   

    public void initialize() { 
     MyGuice.getInjector().inject(this); 
    } 

    @Inject 
    protected void init(Dep1 dep1, Dep2 dep2) { 
     this.dep1 = dep1; 
     this.dep2 = dep2; 
    } 

    private void m() { 
     dept1.doSmth(); 
    } 
} 

的靜態調用是有點反模式的,你可以刪除如果您願意使用代碼編織或後編譯步驟的解決方案,則需要使用簡單註釋來處理後構造器注入。這樣,即使它們沒有初始化方法,也可以注入所有對象。你可以在這裏找到一個例子:How to inject model object with AspectJ

@Configurable 
public class C implements I { 

    public C() { 
     // this ctor is invoked by the framework, you can't do injection here. 
    }   

    @Inject 
    protected void init(Dep1 dep1, Dep2 dep2) { 
     this.dep1 = dep1; 
     this.dep2 = dep2; 
    } 

    private void m() { 
     dept1.doSmth(); 
    } 
} 
+0

感謝Kdeveloper,這更像是原始問題中列出的選項2,並提供了可用於緩解對全局狀態需求的高級技術的有用演示(即:第一個示例中的噴射器)。我的直覺是,在代碼的可維護性方面,補救措施(DI)開始感覺比疾病(服務定位器「反模式」)稍差 - 但儘管如此,代碼的可測試性仍然令人感興趣與靜態注射溶液相比得到改進。 – sxc731 2011-03-21 18:01:17

相關問題