2016-11-30 75 views
2

我試圖從遷移春天有個項目,並開始通過承接來樣GitHub庫用匕首2打一個無效的方法。我怎麼能「提供」中的匕首

在春天,我可以在類級別使用註釋來揭露所有的類的方法,包括void方法。我想在匕首2中這樣做,即我想'提供'void方法。

在下面的代碼示例中,我應該將printRandomUUID方法移動到Printer接口。不過,我正在做這個小練習,目的是遷移經典的彈簧@Component@Service

什麼是正確的方法?是否有可能在組件或模塊級別提供無效方法?

public class Main { 

interface Printer { 

    void printMsg(String msg); 
} 

static class ConsolePrinter implements Printer { 

    @Override 
    public void printMsg(String msg) { 
     System.out.println(msg); 
    } 
} 

@Singleton 
@Component(modules = ConsoleModule.class) 
interface HelloWorldApp { 

    Printer getPrinter(); 

    //this doesn't compile -> java.lang.IllegalArgumentException: not a valid component method: 
    void printRandomUUID(); 
} 

@Module 
static class ConsoleModule { 

    @Provides 
    Printer providePrinter() { 
     return new ConsolePrinter(); 
    } 

    //this doesn't compile -> @Provides methods must return a value (not void) 
    @Provides 
    void printRandomUUID() { 
     System.out.println(UUID.randomUUID().toString()); 
    } 

} 

public static void main(String[] args) { 
    HelloWorldApp app = DaggerMain_HelloWorldApp.create(); 
    app.getPrinter().printMsg("Hello"); 
    System.out.println("-"); 
    //app.printRandomUUID();//here i want a void method to be consumed, from the component. 
} 
} 
+2

這似乎是一個超級奇怪的事情想要的。你能提供一個'Runnable'回調嗎? –

回答

3

這是不可能的(還)。與Spring不同,Dagger只能通過檢查組件接口和模塊進行配置。這意味着匕首@Component的方法必須是match the format of the methods from the @Component documentation,目前還沒有辦法提供委託給其他實例的任意代碼或方法。

這並不是說組件不能有void方法:它們可以,但它們被要求是一個參數方法,在外部創建的實例中注入@Inject -annotated方法和字段。這些被稱爲members-injection methods,而不是void他們也可以返回他們接受的類型以便於鏈接。

從不同的角度來看,我認爲,你的匕首創建的組件組合任意的業務邏輯是一個壞主意,爲了簡單和正確性的原因:

  • 這樣做可能違反了SRP或分居關注點:依賴注入的優點之一是將對象創建邏輯與其他業務邏輯分開。允許在對象創建組件上添加業務方法應該與在業務組件中使用new一樣不恰當。 (不管是不是每一個對象應該通過DI圖中可以提供的是另一天是一個有爭議的話題。)
  • 如果你持有到最佳做法,並避免在構造函數/工廠/供應商的副作用等「繁重」,那麼你應該能夠清楚地理解在Component方法中可以發生和不可能發生的事情。允許在組件上使用任意方法 - 尤其是無效方法 - 將與該做法相反。
  • 如果您的應用程序使用單獨的粒度庫而不是整體編譯步驟,那麼從它自己的對象圖中消耗一個Component可能會導致很難在不引入依賴性循環的情況下進行構建。當然,Dagger允許在自己的圖表中注入一個組件,但是這樣做可能會導致循環問題。
  • 類似的使用情況是很容易利用現有的結構來代表 - 使一個可運行可通過圖作爲路易斯Wasserman的評論,或注入了類似的單一目的對象來保存方法 - ,保持任意的實施方式中斷的組件似乎不會導致功能或可讀性的很大損失。在最壞的情況下,您需要一個額外的方法調用來訪問您定義的類。

如果我按照原樣遷移,我將創建一個名爲HelloWorldMethods的HelloWorldApp類,並將所有放在HelloWorldApp上的方法轉移到該類上。如果這是Spring遷移中的常見模式,您甚至可以爲其定義一個本地約定(例如,FooComponent附帶FooMethods或FooUtil)。最後,如果您想隱藏Dagger實現細節(如在外部API中),您也可以編寫自己的類來封裝和使用組件,將重要方法委派給內部組件,並提供您需要的任意實現方式。

+0

FooMethods aproach是我一直在尋找的。當我用匕首做嬰兒步時,我意識到'思考的方式'應該不同,我的意思是一個經典的服務層與春天,不能直接翻譯DI的Dagger方式。 – whyem

+0

@whyem對,Dagger組件是提供服務或實例化服務的好方法,但它們本身並不擅長服務。從好的一面來看,您可以更清楚地控制哪些服務接口和實現看起來像必須與組件接口分開。 –