【问题标题】:Use Guice nested injects使用 Guice 嵌套注入
【发布时间】:2017-11-07 13:13:04
【问题描述】:

我对 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 的初学者,所以请对我温柔一点。

我想使用构造函数注入,我已经意识到字段注入被认为是“邪恶的”。您是否知道如何通过保留提供者(我需要它们)来使其正常工作?

使用示例中的注入在“第二”级别上没有任何作用,LogInServiceImpl 中的DatabaseControllerImplnull

我是不是配置有问题?我是否误解了提供和/或模块的用法?

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

致以最诚挚的问候,

约瑟夫背包

【问题讨论】:

    标签: dependency-injection guice


    【解决方案1】:

    您的直接回答:您在 Providers 中调用 new T();,它不支持字段注入。

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

    包含几个默认绑定:

    • 这个 Injector 实例本身
    • Provider&lt;T&gt; 用于 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);
        }
    }
    

    然后,您将拥有与现在相同的选择,注入 TProvider&lt;T&gt; 并根据需要调用 getInstancegetProvider


    如果您的 Providers 绝对必要,特别是如果他们实际上从其他系统或服务定位器接收实例,另一种选择是将您的 @Inject 字段添加到其中,如 @987654323 @ 并将它们传递给您的构造函数,或者只是传递给inject a MembersInjector&lt;T&gt;

    public class LogInServiceProvider implements Provider<LogInServiceInterface> {
        @Inject MembersInjector<LogInServiceImpl> logInServiceImplInjector;
    
        @Override
        public LogInServiceInterface get() {
            LogInServiceImpl logInServiceImpl = YourExternalDep.getLogInService();
            logInServiceImplInjector.injectMembers(logInServiceImpl);
            return logInServiceImpl;
        }
    }
    

    但是,此显式提供程序解决方案不是惯用的 Guice,只能与外部或遗留代码一起使用。 Guice 存在的全部原因是自动化样板文件并让您的系统清晰灵活地组合在一起。提供者是一个实现细节;让 Guice 为您创建它们。

    【讨论】:

    • 非常感谢!这真的帮助了我!我想它也适用于 Guice 的 JPA Persistence Provider,对吗?真的加深了我对Guice的理解!
    • @JosefRucksack 很高兴为您提供帮助!恐怕我没有机会使用 JPA,所以我不确定,但我没有看到任何 in the docs 暗示需要明确的 Guice 对象提供者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 2013-07-01
    相关资源
    最近更新 更多