java - 是否有可能优雅地提供来自 Guice 辅助注入(inject)工厂的不包含参数或等效项的实例?

标签 java guice-3

好的,所以下面的代码失败了。但是,如果存在多个潜在的 View 实例,那么在您想要使用它们的地方注入(inject)大量 Provider 提供程序会感觉很笨拙。这在我的情况下可能是可行的,但是我可以想象在其他情况下这并不是很好......所以我想我会在我脑海中浮现出这个问题时提出这个问题。我还没有尝试过的一种解决方案是向方法添加虚拟 @Assisted 参数并像factory.getView1(null) 一样进行调用,尽管这也不是很好。

注意,我可以理解为什么对于 guice 实现者来说这将是一个极端情况,因为 guice 必须知道不要调用构造函数(看起来是这样)而是使用提供程序(它在技术上是知道的) 。不过,最好还是询问是否有解决方案,而不是假设没有解决方案。 :-)

import com.google.inject.*;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import junit.framework.Assert;
import org.junit.Test;


public class GuiceTests {

    static class View1 implements Presenter.View {
        String name = null;
        @Override
        public String getName() { return null; }
        public void setName(String name) { this.name = name ;}
    }
    static class View2 extends View1 {}
    static class Presenter {
        interface View {public String getName();}
        @Inject
        public Presenter(@Assisted View view //, and other injected services
        ){}
    }

    interface Factory{
        Presenter getPresenter(Presenter.View view);
        View1 getView1();
        View2 getView2();
    }

    static class Module extends AbstractModule
    {
        @Provides View1 getView1()
        {
            View1 view1 = new View1(); //or possibly get this from an xml generator
            view1.setName("buddy");
            return view1;
        }

        @Override
        protected void configure() {

            install(new FactoryModuleBuilder().implement(Presenter.class, Presenter.class)
                    .build(Factory.class));
        }
    }

    /**
     * We're testing the ability here for assisted injected factories
     * to be used to produce entities provided by the module with NO
     * assisted arguments. This way they can conveniently be used in
     * conjuction with other factory assisted methods as shown below.
     * This fails!
     */
    @Test
    public void testAssisted()
    {
        Injector injector = Guice.createInjector(new Module());

        Factory factory = injector.getInstance(Factory.class);
        View1 view1 = factory.getView1();
        Assert.assertEquals("buddy", view1.getName());
        Presenter presenter = factory.getPresenter(view1);

    }
}

额外上下文

艾伦在下面问道:“你能举一个例子,说明使用这个(不调用注入(inject)器)的真实代码是什么样子吗?我不明白为什么你不直接将工厂和相关 View 一起注入(inject)(或者为执行此操作的每种风格的演示者定义一个带注释的提供方法)”

所以我有一个演示者,它被可视化为一张 float 布局的卡片。该演示者具有一定的业务逻辑,可以使用一组服务来配置自身。应用程序中有一个“新建”按钮,它为您提供了卡的 View ,引导您完成新流程(卡上的配置)。构建卡片后,就会有一个不同的 View 来表示卡片...但它共享许多相同的业务逻辑...所以理想情况下,我想重用已经使用模型配置的演示者...但现在附加建成的 View 。使用构建 View 重新创建持久卡。 除非您关注该讨论,否则请不要阅读。

请注意,上面的代码充分提炼了我遇到的问题。下面使事情变得复杂,因为它提供了更完整的上下文。

//----------------

//on Add new entity
cardLayout.add(factory.getPresenterWithWizardView());

//-----------
//then later in the finish of the wizard
thePresenter.setView(factory.getConstructedView());
//I would prefer not to create a new presenter here, as the presenter also has layout
//state and logic that maintains and interacts with cardLayout to . Allowing for removing
//and adding a different presenter would trigger stuff affecting the state.

//--------------
//however elsewhere cards are loaded with 
cardLayout.add(factory.getPresenterWithBuiltView(cardFromDb));

最佳答案

如果您知道需要演示者呈现特定 View ,我会向您的模块添加如下内容:

@Provides @Named("PresenterForView1")
public Presenter forView1(Factory factory, View1 view1) {
  return factory.getPresenter(view1);
}

(仅使用正确的注释而不是名称,并对各种预设 View 重复。)

当您稍后想要更改演示者的 View 时,我只需注入(inject)该 View :

@Inject Constructor(@Named("PresenterForView1") Presenter presenter, View2 view2) {
  ...
  presenter.setView(view2);
  ...
}

(或者如果您不希望提前构造它,也可以注入(inject) Provider<View2>。)

关于java - 是否有可能优雅地提供来自 Guice 辅助注入(inject)工厂的不包含参数或等效项的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23581871/

相关文章:

java - HashMap 和 HashSet 有什么共同点?

java - Spring 应用程序上下文 XML 的命名约定

java android 创建事件

java - Guice MethodInterceptor 应该返回什么

java - Guice 在 AbstractModule 之间合并集合

java - 复杂 GUI 程序中的 MVC 模式

java - 如何解决 Java 和 Spring Boot 中的 slf4j logback 类路径错误?

Guice,使用 @AssistedInject 时注入(inject) TypeLiteral<T>

java - Guice3 Singleton 从未在 GAE 项目中实例化