2016-12-25 63 views
2

我正在創建庫並幫助人體工程學,我將在應用程序啓動時創建的注入器傳遞給庫中的不同組件,以便用戶可以在特定上下文中執行getInstance(),計劃在哪裏粘貼他們的@Inject註釋。Guice的全球注射器

這裏的API設計的一個例子:

public static void main(String[] args) { 
    // Main injector is created here behind the scenes. 
    ApexApplication app = new ApexApplication() 

    app.get("https://stackoverflow.com/users/:id", context -> { 
    // Users can do this instead of @Inject UserDAO dao 
    UserDAO dao = context.getInstance(UserDao.class) 
    User user = dao.findUserById(context.param("id")) 
    //... 
    }) 
    app.start(); 
} 

這裏是鏈接到關鍵實施細節清晰:

  • #1:這裏是我創建初始(只)噴油器
  • #2:然後我將它作爲其構造函數的一部分傳遞給另一個庫組件
  • #3:其他組件然後委託調用getInstance()到原來的注射器

我知道最好的做法WRT吉斯噴射器是創建一個且只有一個在整個應用程序,用它來注入所有的依賴關係,然後把它遠;然而,鑑於我想要實現的目標,是否會推薦這種方法,或者我應該考慮另一種模式?

+0

如果你爲Guice模塊引入一個類似'MyModuleHelper'的並行類,你可以避免繞過注入器,並且更加明確地訪問它。在其中,填充通過調用模塊上的getInstance()來初始化的'public static final'字段(或者helper類中的靜態方法)。然後,直接從代碼庫中直接使用這些常量字段,而不是通過噴油器。 – Jameson

+0

@Jameson我不確定我是否關注。你能舉個例子嗎? – kshep92

回答

0

我接受了你的建議@asch,但稍微改了一下,允許用戶設置他自己的配置模塊。

public class DependencyManager { 
    private static Injector injector; 
    private static Logger logger = LoggerFactory.getLogger(DependencyManager.class); 

    public static Injector initializeWith(ApexConfiguration configuration) { 
     if(injector == null) { 
      logger.debug("Initializing injector") 
      injector = Guice.createInjector(configuration); 
     } 
     return getInjector(); 
    } 

    public static Injector getInjector() { 
     if(injector == null) { 
      logger.error("Application hasn't been configured yet."); 
      return null; 
     } 
     return injector; 
    } 

    private DependencyManager() {} 
} 

我不能完全肯定它是線程安全的,但在我所有測試的執行,日誌消息Initializing injector只顯示一次,並呼籲getInjector()時,我從來沒有得到一個NullPointerException

我相信這是因爲庫的結構,DependencyManager必須在任何其他應用程序操作發生之前自動初始化。

歡迎任何意見/建議,以改善這一點。

0

我不認爲將注射器的上下文發送到每個其他類以獲得進樣器是不錯的主意。

還有一種方法,實際上和@Jameson的MyModuleHelper的想法非常相似。 DIContainer對注入器進行靜態初始化,並提供公共靜態API getInjector()。這樣你可以有注射器,其中創建只有一次,它是提供給任何類沒有樣板代碼:

public final class DIContainer { 
    private static final Injector injector; 
    static { 
     injector = Guice.createInjector(new AppModule()); 
    } 
    public static Injector getInjector() { 
     return injector; 
    } 
    private DIContainer() { 
    } 
} 

用例:

ServiceProvider service = DIContainer.getInjector().getInstance(ServiceProvider.class); 

可能this post是有用的。

+0

但這是一種安全的方法嗎?該庫基於多線程的Vertx。 – kshep92

+0

靜態初始化塊是線程安全的。 – asch

+0

這就是事情變得棘手的地方,因爲用戶應該能夠指定一個配置模塊,而不必自己創建其中的一個類。 'ApexApplication'的一個構造函數採用'AbstractModule'。 – kshep92