在非 guice class 中注入 guice 管理的依赖
Inject guice managed dependency in a non guice class
我有一个 class (CustomConnectionProvider
),它将由第三方库 (hibernate) 使用 class.forName().newInstance()
实例化。我需要注入一个 guice 管理的依赖关系,比如 MyDatabaseFactory
,它将为多租户提供数据源。
我不能直接@Inject
MyDatabaseFactory,因为CustomConnectionProvider
不是托管bean。而且我无法控制它的创建方式。
我刚开始使用 Guice 作为 Play 应用程序的一部分。任何例子或想法将不胜感激,我正在寻找像 ServiceLocator
.
这样的解决方案
针对特定情况修复
幸运的是,Play.application()
提供了一个静态方法来获取 injector
,我正在使用它来获取我的工厂实例。我还想知道是不是非玩不可修复
Play 2.5 更新
Play.application()
在 2.5 中已弃用。我们需要按照罗伯特的建议使用静态注入。
您可以使用静态注入。参见 https://github.com/google/guice/wiki/Injections
It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. Use
requestStaticInjection()
在模块中指定 class 在注入器创建时注入:
@Override public void configure() {
requestStaticInjection(ProcessorFactory.class); ... }
Guice 将注入 class 具有@Inject 注释的静态成员。
其实requestStaticInjection
不是推荐的方式。正如 this link 解释的那样 (This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
),它在少数情况下会产生很多问题。行为不一致,每次注入都不成功。
我不得不采取稍微不同的方法:我的情况有点复杂,我的 class 实例将由 Hibernate 使用 Class.forName()
创建,这可能是静态注入 可能失败。
我必须创建一个 Singleton 工厂,它将在模块创建开始时被初始化并绑定到 Guice Injector,这个工厂将保存我需要注入到我的实际 class 中的实际 bean。它提供了一个静态方法来获取所需的bean。
public Class RequiredBeanFactory {
private static RequiredBean bean;
//note this is a package private
RequiredBeanFactory(RequiredBean bean) {
this.bean = bean;
}
public static RequiredBean getBean() {
return bean;
}
}
在我的模块中,我正在对其进行初始化和绑定。
public class MyModule extends AbstractModule {
private final RequiredBean bean;
@Inject
public MyModule(RequiredBean bean) {
this.bean = bean;
}
protected void configure() {
RequiredBeanFactory factory = new RequiredBeanFactory(this.bean);
bind(RequireBeanFactory.class).toInstance(factory);
}
}
在我的 HibernateCustom class 中,我只使用 RequiredBeanFactory.getBean()
。
这是一种 hack,可能具有与 Guice 提到的相同的副作用,但它在我的控制之下并且行为是一致的。
我有一个 class (CustomConnectionProvider
),它将由第三方库 (hibernate) 使用 class.forName().newInstance()
实例化。我需要注入一个 guice 管理的依赖关系,比如 MyDatabaseFactory
,它将为多租户提供数据源。
我不能直接@Inject
MyDatabaseFactory,因为CustomConnectionProvider
不是托管bean。而且我无法控制它的创建方式。
我刚开始使用 Guice 作为 Play 应用程序的一部分。任何例子或想法将不胜感激,我正在寻找像 ServiceLocator
.
针对特定情况修复
幸运的是,Play.application()
提供了一个静态方法来获取 injector
,我正在使用它来获取我的工厂实例。我还想知道是不是非玩不可修复
Play 2.5 更新
Play.application()
在 2.5 中已弃用。我们需要按照罗伯特的建议使用静态注入。
您可以使用静态注入。参见 https://github.com/google/guice/wiki/Injections
It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. Use
requestStaticInjection()
在模块中指定 class 在注入器创建时注入:
@Override public void configure() {
requestStaticInjection(ProcessorFactory.class); ... }
Guice 将注入 class 具有@Inject 注释的静态成员。
其实requestStaticInjection
不是推荐的方式。正如 this link 解释的那样 (This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
),它在少数情况下会产生很多问题。行为不一致,每次注入都不成功。
我不得不采取稍微不同的方法:我的情况有点复杂,我的 class 实例将由 Hibernate 使用 Class.forName()
创建,这可能是静态注入 可能失败。
我必须创建一个 Singleton 工厂,它将在模块创建开始时被初始化并绑定到 Guice Injector,这个工厂将保存我需要注入到我的实际 class 中的实际 bean。它提供了一个静态方法来获取所需的bean。
public Class RequiredBeanFactory {
private static RequiredBean bean;
//note this is a package private
RequiredBeanFactory(RequiredBean bean) {
this.bean = bean;
}
public static RequiredBean getBean() {
return bean;
}
}
在我的模块中,我正在对其进行初始化和绑定。
public class MyModule extends AbstractModule {
private final RequiredBean bean;
@Inject
public MyModule(RequiredBean bean) {
this.bean = bean;
}
protected void configure() {
RequiredBeanFactory factory = new RequiredBeanFactory(this.bean);
bind(RequireBeanFactory.class).toInstance(factory);
}
}
在我的 HibernateCustom class 中,我只使用 RequiredBeanFactory.getBean()
。
这是一种 hack,可能具有与 Guice 提到的相同的副作用,但它在我的控制之下并且行为是一致的。