Я расширяю Guice AbstractModule
и внутри расширяющегося класса мне нужен доступ к инжектору Гизе. Это возможно, если да, то как?
Доступ к инжектору Guice в его модуле?
Ответ 1
Это необычный запрос. Модули больше похожи на файлы конфигурации, чем на логические файлы. Модуль читается для создания Инжектора, а затем, как только инжектор создается, модуль выполнил свою работу. Для простого модуля инжектор буквально не существует, пока модуль не будет готов к отбрасыванию.
В любом случае, вместо того, чтобы запрашивать инжектор для получения класса X, вы обычно должны запрашивать Provider<X>
. Guice будет введите X
или Provider<X>
для привязки X
, Provider<X>
или @Provides X
, поэтому вы почти всегда можете это сделать. Тем не менее, инъекция инжектора позволит вам получить экземпляр рефлексивно или проверить привязки инжектора (и т.д.).
Вот несколько веских причин/конструкций, которые требуют доступа к инжектору из модуля:
В методе @Provides
:
Модули могут содержать мини-провайдеров в методах, аннотированных с помощью @Provides
. Помните, что Injector
используется для инъекций: если вам нужен инжектор в одном из этих методов, вы можете просто принимайте его как параметр:
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
}
}
Чтобы получить поставщика в вашем 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)
, но я не знаю, работает ли это, и я не знаю, почему вы хотите.
Чтобы получить экземпляр в вашем configure():
Это плохая идея; Guice не готов предоставлять экземпляры до тех пор, пока не будут запущены все методы настройки. Самое близкое, что вы можете получить, это создать дочерний инжектор, используя другие модули и передать его в этот модуль, но даже это редко требуется.
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 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);
}
}