带有 Guice 的全局注入器
Global injectors with 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();
}
为清楚起见,以下是关键实施细节的链接:
我知道 Guice 注入器的最佳实践是在整个应用程序中只创建一个,用它来注入所有依赖项,然后将其丢弃;但是,考虑到我想要实现的目标,是否会推荐这种方法或者我应该研究另一种模式?
我认为将带有注入器的上下文发送给每个其他人 class 以访问注入器并不是一个好主意。
还有一种方法,其实和@Jameson的MyModuleHelper的思路很像。 DIContainer 对注入器进行静态初始化并提供 public static API getInjector()。这样你就可以拥有注入器,它只创建一次并且可以用于任何 class 没有样板代码的东西:
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 也很有用。
我听取了@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
13=].
我认为这是因为库的结构,DependencyManager
必须在任何其他应用程序操作发生之前自动初始化。
欢迎任何comments/suggestions对此进行改进。
我正在创建一个库,为了帮助实现人体工程学,我将在应用程序启动时创建的注入器传递给库中的不同组件,以便用户可以在某些上下文中执行 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();
}
为清楚起见,以下是关键实施细节的链接:
我知道 Guice 注入器的最佳实践是在整个应用程序中只创建一个,用它来注入所有依赖项,然后将其丢弃;但是,考虑到我想要实现的目标,是否会推荐这种方法或者我应该研究另一种模式?
我认为将带有注入器的上下文发送给每个其他人 class 以访问注入器并不是一个好主意。
还有一种方法,其实和@Jameson的MyModuleHelper的思路很像。 DIContainer 对注入器进行静态初始化并提供 public static API getInjector()。这样你就可以拥有注入器,它只创建一次并且可以用于任何 class 没有样板代码的东西:
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 也很有用。
我听取了@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
13=].
我认为这是因为库的结构,DependencyManager
必须在任何其他应用程序操作发生之前自动初始化。
欢迎任何comments/suggestions对此进行改进。