在其模块中访问Guice注射器? [英] Accessing Guice injector in its Module?

查看:120
本文介绍了在其模块中访问Guice注射器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在扩展Guice的 AbstractModule ,而在扩展类之内,我需要访问Guice的注入器。这可能,如果是,怎么样?

解决方案

这是一个不寻常的请求。模块更像是配置文件而不是逻辑文件:读取模块以创建注入器,然后只要注入器被创建,模块就完成了它的工作。对于一个简单的模块,在模块准备好被丢弃之前,注射器字面上不存在。



无论如何,不​​是请求一个注射器来获取类X,你通常应该要求一个 Provider< X> 。 Guice将 X X Provider< X> c $ c>, Provider< X> @Provides X ,所以你几乎可以这样做也就是说,注射注射器将允许您反映实例,或检查注射器的绑定(等)。



以下是一些有效的原因/设计,需要在模块内访问注射器:



@Provides 方法中:



模块可以在注释为 @Provides 。请记住, 注射器是可注射的:如果您需要在其中一种方法中使用注射器,则可以接受它作为参数:

  public class OneModule extends AbstractModule {
@Override public void configure(){/ * ... * /}

@Provides YourDependency getYourDependency(注射器注射器){
return inject.getInstance(Class.forName(yourDependencyName));
}

@Provides Something getSomething(SomethingImpl something){
return initialize(something); //首选:只要求你需要什么
}

@Provides SomethingElse getSomethingElse(Provider< Thing> thingProvider){
return new SomethingElse(thingProvider); //要求提供者的工作也是
}
}



您的configure()中的提供者:



AbstractModules公开 getProvider() 正是因为这个原因,如果您在注射器准备好提供(如配置时)之前调用 get(),那么您将收到错误:

  public class TwoModule extends AbstractModule {
@Override public void configure(){
bind(Thingy.class).toInstance(
new MyThingy(8675309,getProvider(Another.class)));
}
}

你可以调用 getProvider (Injector.class)但我不知道这是否有效,我不知道你为什么想要。



To在你的configure()中获得一个实例:



这是一个坏主意;在所有配置方法运行之前,Guice尚未准备提供实例。你最接近的是创建一个孩子注射器,使用其他模块并将其传递到此模块中,但即使这样也很少需要。



公共类MainClass {
public static void main(String [] args){
注入器firstStage =
Guice.createInjector(new OtherModule1() ,新的OtherModule2());
//另一种设计可以在3Module
//中注入 - 注释字段,并从firstStage获取它,但这是非标准的,可能会令人困惑。
注射器secondStage =
firstStage.createChildInjector(new ThreeModule(firstStage));
}
}

public class ThreeModule extends AbstractModule {
private final Injector otherInjector;

public ThreeModule(Injector otherInjector){
this.otherInjector = otherInjector;
}

@Override public void configure(){
bindStuffBasedOn(otherInjector);
}
}


I am extending Guice's AbstractModule and inside of the extending class I need access to Guice's injector. It that possible, if yes, how?

解决方案

This is an unusual request. Modules are more like config files than logic files: The Module is read to create the Injector, and then as soon as the Injector is created the module has done its job. For a simple Module, the Injector literally doesn't exist until the Module is ready to be discarded.

In any case, rather than requesting an Injector to get class X, you should typically request a Provider<X>. Guice will inject an X or Provider<X> for any binding of X, Provider<X>, or @Provides X, so you can almost always do this instead. That said, injecting the Injector will allow you to get an instance reflectively, or to inspect the Injector's bindings (etc).

Here are a few valid reasons/designs that would require accessing an Injector from within a Module:

In a @Provides method:

Modules can contain mini-providers in methods annotated with @Provides. Remember that Injector is injectable: If you need an Injector in one of those methods, you can just accept it as a parameter:

public class OneModule extends AbstractModule {
  @Override public void configure() { /* ... */ }

  @Provides YourDependency getYourDependency(Injector injector) {
    return injector.getInstance(Class.forName(yourDependencyName));
  }

  @Provides Something getSomething(SomethingImpl something) {
    return initialize(something); // preferred: only ask for what you need
  }

  @Provides SomethingElse getSomethingElse(Provider<Thing> thingProvider) {
    return new SomethingElse(thingProvider); // asking for a provider works too
  }
}

To get a Provider in your configure():

AbstractModules expose getProvider() for exactly this reason, though you'll get an error if you call get() on that Provider before the injector is ready to provide it (such as at configuration time):

public class TwoModule extends AbstractModule {
  @Override public void configure() {
    bind(Thingy.class).toInstance(
        new MyThingy(8675309, getProvider(Another.class)));
  }
}

You can probably call getProvider(Injector.class) but I don't know whether that works and I don't know why you'd want to.

To get an instance in your configure():

This is a bad idea; Guice is not ready to provide instances until after all of the configure methods run. The closest you can get is to create a child Injector using the other modules and pass it into this module, but even that is rarely needed.

public class MainClass {
  public static void main(String[] args) {
    Injector firstStage =
        Guice.createInjector(new OtherModule1(), new OtherModule2());
    // An alternative design would @Inject-annotate fields in ThreeModule
    // and get it from firstStage, but that's nonstandard and may be confusing.
    Injector secondStage =
        firstStage.createChildInjector(new ThreeModule(firstStage));
  }
}

public class ThreeModule extends AbstractModule {
  private final Injector otherInjector;

  public ThreeModule(Injector otherInjector) { 
    this.otherInjector = otherInjector;
  }

  @Override public void configure() {
    bindStuffBasedOn(otherInjector);
  }
}

这篇关于在其模块中访问Guice注射器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆