Java 多个喷油器参考出现不可避免的Guice场景

Java 多个喷油器参考出现不可避免的Guice场景,java,guice,Java,Guice,我有一个用例,在这个用例中,从多个位置引用Guice注入器似乎是唯一的解决方案,尽管通常不鼓励这样做 我的应用程序构建在Talend之上,Talend是一个开源ETL平台。我的大多数实际应用程序都在由Talend组件调用的Java类中。这些组件包括我编写的Java代码段,这些代码段依次实例化/调用我的类 现在,我打算在我的Java类中使用Guice,但我绝对没有办法将依赖项注入到Talend组件中(以便Java代码段可以使用它们)。相反,我需要实际创建这些依赖项。我希望至少让Guice控制实例化

我有一个用例,在这个用例中,从多个位置引用Guice注入器似乎是唯一的解决方案,尽管通常不鼓励这样做

我的应用程序构建在Talend之上,Talend是一个开源ETL平台。我的大多数实际应用程序都在由Talend组件调用的Java类中。这些组件包括我编写的Java代码段,这些代码段依次实例化/调用我的类

现在,我打算在我的Java类中使用Guice,但我绝对没有办法将依赖项注入到Talend组件中(以便Java代码段可以使用它们)。相反,我需要实际创建这些依赖项。我希望至少让Guice控制实例化,这意味着不用
new
,我可以实例化我的类(使用
@Inject
构造函数的类)的唯一方法是调用
injector.getInstance
。这反过来意味着我需要保留喷油器,大概是使用一个老式的工厂,它首先创建喷油器,并将其作为一个单体提供

我只是找不到任何其他方法来处理这个问题,但也许我遗漏了什么。

考虑一下。这仍然会在应用程序中隐藏对注入器的持久引用,但它将使您不必在代码中添加
injector.getInstance(…)
调用。在任何情况下,如果确实需要,您都可以注入
Injector

class TalendDependencyModule extends AbstractModule {
  @Override public void configure() {
    requestStaticInjection(ExtractorDependencies.class);
    requestStaticInjection(ProcessorDependencies.class);
  }
}

public class ExtractorDependencies {
  @Inject private static Provider<ParserService> parserServiceProvider;
  @Inject private static Provider<SomethingElse> somethingElseProvider;

  private ExtractorDependencies() { }

  static ParserService getParserService() {
    return parserServiceProvider.get();
  }

  /* ... */
}
类TalendDependencyModule扩展了AbstractModule{
@重写公共void configure(){
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
公共类提取器依赖项{
@注入私有静态提供者parserServiceProvider;
@注入私有静态提供者somethingelesprovider;
私有提取器Dependencies(){}
静态ParserService getParserService(){
返回parserServiceProvider.get();
}
/* ... */
}
考虑一下。这仍然会在应用程序中隐藏对注入器的持久引用,但它将使您不必在代码中添加
injector.getInstance(…)
调用。在任何情况下,如果确实需要,您都可以注入
Injector

class TalendDependencyModule extends AbstractModule {
  @Override public void configure() {
    requestStaticInjection(ExtractorDependencies.class);
    requestStaticInjection(ProcessorDependencies.class);
  }
}

public class ExtractorDependencies {
  @Inject private static Provider<ParserService> parserServiceProvider;
  @Inject private static Provider<SomethingElse> somethingElseProvider;

  private ExtractorDependencies() { }

  static ParserService getParserService() {
    return parserServiceProvider.get();
  }

  /* ... */
}
类TalendDependencyModule扩展了AbstractModule{
@重写公共void configure(){
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
公共类提取器依赖项{
@注入私有静态提供者parserServiceProvider;
@注入私有静态提供者somethingelesprovider;
私有提取器Dependencies(){}
静态ParserService getParserService(){
返回parserServiceProvider.get();
}
/* ... */
}

<>代码> 我不知道你有多少个Talm对象,但你可能想考虑使用提供者。例如,假设您有自己的类,希望Guice管理其创建:

public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
这将被添加到一个Talend对象中,该对象的依赖项不能通过Guice注入(尽管我假设有一些手动过程可以通过构造函数或setter注入):

如果希望Guice管理这些生命周期和Talend受控对象的生命周期,可以使用如下提供程序:

public static class TestModule extends AbstractModule {
            @Override
            protected void configure() {
                bind(INotTalendControlled.class).to(NotTalendControlled.class);
            }

            @Provides
            public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
                return new TalendControlled(notTalendControlled);
            }
        }

< P>方法将隐藏所有对象的新用法,因为您现在可以直接注入TalEnDebug对象(@注入TalenControlled talendControlled),而不需要显式注入器来构造它们的依赖关系。

< P>我不知道您有多少个Talm对象,但您可能需要考虑使用提供者。例如,假设您有自己的类,希望Guice管理其创建:

public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
这将被添加到一个Talend对象中,该对象的依赖项不能通过Guice注入(尽管我假设有一些手动过程可以通过构造函数或setter注入):

如果希望Guice管理这些生命周期和Talend受控对象的生命周期,可以使用如下提供程序:

public static class TestModule extends AbstractModule {
            @Override
            protected void configure() {
                bind(INotTalendControlled.class).to(NotTalendControlled.class);
            }

            @Provides
            public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
                return new TalendControlled(notTalendControlled);
            }
        }

@Provides方法将隐藏new对所有对象的使用,因为您现在可以直接注入TalendControld对象(@inject TalenControlled TalendControld),并且不需要显式注入程序来构造它们的依赖项。

杰夫,您的回答很准确。我非常感激,;您的帮助对我规划Guice迁移的能力产生了明显的影响,这必须很快实现。我承认,大约一周前读过关于静态注入的文章后,我在心里放弃了它,因为我不会用它玷污我的代码。这将教会我如何避免极客势利:-)我确实想确认一件事。考虑静态注入的提供者,<代码> > PARSerServServices < /代码>,您是在上面发明的。code>ExtractorDependencies.getParserService()
将在策略转换过程中被下游调用。实际上,
ParserService
可能已经注入了依赖项,例如PolicyContext(请参见在该提供程序上调用“get”时,对象将实际实例化(假设提供的对象实际上不是单例对象)。当您插入某个对象的实例而不是提供程序时,Guice将为您隐式调用提供程序,因此逻辑仍然有效。您可以将作用域视为集中配置的提供程序装饰器,以及作用域返回的提供程序(如SimpleScope中的提供程序)碰巧是一个匿名的内部类--它应该可以保护您,使您不会意外地将错误的PolicyContext保存到它不属于的位置。这是一种有效的方法,但我个人不会使用静态注入。我更愿意在应用程序的引导过程中手动设置这些提供程序。这样可以更清楚地了解实际发生的情况g、 @RobbieV很公平,尽管Guice的部分目的是减少(非常明显的)样板——毕竟,将它们设置为manu