Guice的全球注射器

时间:2016-12-25 02:11:44

标签: java dependency-injection guice

我正在创建一个库并帮助人体工程学,我将在应用程序启动时创建的注入器传递给库中的不同组件,以便用户可以在某些情境中执行getInstance()必须预先计划在哪里粘贴@Inject注释。

以下是API设计的一个示例:

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

  app.get("/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()的调用委托给原始注入器

我知道Guice注入器的最佳实践是在整个应用程序中创建一个且只有一个,使用它来注入所有依赖项,然后将其丢弃;但是,考虑到我想要实现的目标,是推荐这种方法还是我应该研究另一种模式?

2 个答案:

答案 0 :(得分: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也很有用。

答案 1 :(得分: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只显示一次而我从未得到NullPointerException在致电getInjector()时。

我认为这是因为DependencyManager必须在," abc def , qwerty ghans , ghjt bnsn 5667w !*? ", 所必需的位置构建库,并且在任何其他应用程序操作发生之前自动初始化。

欢迎任何改进此事的意见/建议。