使用Guice嵌套注入

时间:2017-11-07 13:13:04

标签: dependency-injection guice

我对Guice来说相对较新,有些事情仍然让我很难过。 我特别的问题是,你如何在Guice中处理嵌套注射。 示例:

A类通过@Inject使用B类,B类使用C类。

显式:

我的模块,我绑定到提供商。

public class ModuleBinder extends AbstractModule {

    @Override
    protected void configure() {
        bind(DatabaseControllerInterface.class)
        .toProvider(DatabaseControllerProvider.class).asEagerSingleton();

        bind(AnalyzerInterface.class)
        .toProvider(AnalyzerProvider.class).asEagerSingleton();

        bind(SystemAdministrationInterface.class)
        .toProvider(SystemAdministrationProvider.class).asEagerSingleton();

        bind(LogInServiceInterface.class)
        .toProvider(LogInServiceProvider.class);
    }
}

DatabaseControllerProvider:

public class DatabaseControllerProvider implements Provider<DatabaseControllerInterface> {

    @Override
    public DatabaseControllerInterface get() {
        return new DatabaseControllerImpl();
    }
}

LogInServiceProvider:

public class LogInServiceProvider implements Provider<LogInServiceInterface> {

    @Override
    public LogInServiceInterface get() {
        return new LogInServiceImpl();
    }
}

最后,LogInService使用:

public class LogInServiceImpl implements LogInServiceInterface{

    @Inject
    private DatabaseControllerProvider databaseControllerProvider;

    private final DatabaseControllerInterface databaseController;


    public LogInServiceImpl() {
         this.databaseController = databaseControllerProvider.get();
    }

    @Override
    public User register(final String mail, final String userName, final String password) {
        databaseController.registerUser(userName, mail, password, UserRole.ADMIN);
    }

}

然后打电话:

public class Test() {
     public static test() {
         final Injector injector = Guice.createInjector(new ModuleBinder());
         logInService = injector.getInstance(LogInServiceInterface.class);
         logInService.registerUser("test", "test", "test");
      }
}

我知道你们中的大多数人都会厌倦那些代码,但是,嘿,我是Guice的初学者,所以请温柔地对待我。

我想使用Constructor注入,我已经意识到现场注入被认为是&#34; evil&#34;。您是否知道如何通过保留提供商(我需要它们)来实现这一目标?

使用示例中的注入对&#34; second&#34;级别,DatabaseControllerImpl中的LogInServiceImplnull

我配错了吗?我是否误解了提供和/或模块的用法?

我希望有人可以而且想要帮助我。如果您需要更多信息,请发表评论。

最诚挚的问候,

JosefRucksack

1 个答案:

答案 0 :(得分:0)

您的直接答案:您在提供商中呼叫new T();,但不支持现场注入。

首先,真正节省时间:不要保留明确的提供商。如果您绑定了T,Guice允许您为Provider注入Injector.getProvider或致电T,即使您尚未自己明确创建提供商。请参阅维基上的Built-In Bindings页面,  或Injector docs(强调我的):

  

包含多个默认绑定:

     
      
  • 此Injector实例本身
  •   
  • Provider<T>类型T的每个绑定的public class ModuleBinder extends AbstractModule { @Override protected void configure() { bind(DatabaseControllerInterface.class) .to(DatabaseControllerImpl.class).asEagerSingleton(); bind(AnalyzerInterface.class) .to(AnalyzerImpl.class).asEagerSingleton(); bind(SystemAdministrationInterface.class) .to(SystemAdministrationImpl.class).asEagerSingleton(); bind(LogInServiceInterface.class) .to(LogInServiceImpl.class); } }
  •   
  • 正在注入的类的记录器
  •   
  • 创建注射器的阶段
  •   

相反,这样做:

T

您现在可以选择同一个注入Provider<T>getInstance并根据需要致电getProvider@Inject

如果您的提供商绝对必要,特别是如果他们实际从其他系统或服务定位器接收实例,则另一个选项是将public class LogInServiceProvider implements Provider<LogInServiceInterface> { @Inject MembersInjector<LogInServiceImpl> logInServiceImplInjector; @Override public LogInServiceInterface get() { LogInServiceImpl logInServiceImpl = YourExternalDep.getLogInService(); logInServiceImplInjector.injectMembers(logInServiceImpl); return logInServiceImpl; } } 字段添加到其中,如同Provider bindings wiki page并将它们传递给您的构造函数,或仅传递给inject a MembersInjector<T>

{{1}}

但是,此显式提供程序解决方案不是惯用的Guice,只应与外部或遗留代码一起使用。 Guice存在的全部理由是使样板自动化,让您的系统清晰灵活地融合在一起。提供商是一个实施细节;让Guice为你创造它们。