在非 guice class 中注入 guice 管理的依赖

Inject guice managed dependency in a non guice class

我有一个 class (CustomConnectionProvider),它将由第三方库 (hibernate) 使用 class.forName().newInstance() 实例化。我需要注入一个 guice 管理的依赖关系,比如 MyDatabaseFactory,它将为多租户提供数据源。

我不能直接@InjectMyDatabaseFactory,因为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 提到的相同的副作用,但它在我的控制之下并且行为是一致的。