1

假设我们有一个名为 的类Bean,它依赖于另一个名为 的类Service,使用字段注入我们无法更改这些类的代码。另一个类 ( App) 使用 aProvider来随时构造 Bean 的新实例,我们可以随意更改这些类中的代码。

由于在Provider'get()方法中,新实例是使用new运算符创建的,因此无法将 注入Service到 中Bean,因此该Bean实例将不完整(服务字段将为null)。

绕过该问题的一种方法是将InjectorProvider 注入并在新实例上调用injector.injectMembers()该方法。get()

下面是一个代码示例(我避免使用接口来缩短代码)。

class Bean {
    @Inject private Service service;

    public Bean() {
    }

    public void bar() {
        this.service.foo();
    }
}

class Service {

    public void foo() {
        System.out.println("foo");
    }
}

class App {
    @Inject private Provider<Bean> beanProvider;

    public App() {
    }

    public void run() {
        this.beanProvider.get().bar();
    }
}

class BeanProvider implements Provider<Bean> {
    @Inject Injector injector;

    public Bean get() {
        Bean mybean = new Bean();
        this.injector.injectMembers(mybean);

        return mybean;
    }
}

// A simple module to bind the classes
class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(Service.class);
        bind(Bean.class).toProvider(BeanProvider.class);
        bind(App.class);
    }
}


public static void main(String[] args) {
    Injector injector = Guice.createInjector(new MyModule());
    injector.getInstance(App.class).run();
}

另一种方法是将 Bean 更改为使用构造注入,但正如我所说,让我们假设我们不能这样做。

我知道大多数人声称Injector应该避免注入,因为它破坏了整个 DI 理念,因为注入器只能在应用程序的入口点使用,而不能在其他任何地方使用,但是由于 Guice 提供了在应用程序中使用 DI 的不同方法,例如Field Injection,可能会发生像我描述的那种情况。此外,我已经看到在几个项目中经常使用 Field Injection,因此这种情况经常出现。

那么,是否有一种“更清洁”的方法来避免注入Injector我描述的问题?

4

1 回答 1

4

这似乎与您的模块无关。看起来您根本不需要创建提供程序。

您在模块中设置的绑定应该会导致 Service 在您需要的任何地方注入到 Bean 中。因此,您应该能够将 App 中的提供者声明替换为 Bean 注入。

class App {
     @Inject private Bean beanObject;

     public App() {
     }

     public void run() {
         this.beanObject.bar();
     }
}

// A simple module to bind the classes
class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        //bind this to whatever you want to inject into Bean...
        bind(Service.class); 
        bind(Bean.class);
        bind(App.class);
    }
}

如果这对您不起作用,您能否说明您正在尝试做什么以及为什么需要提供者?

于 2014-03-12T22:21:47.100 回答