【问题标题】:Delay object injection in Guice?在 Guice 中延迟对象注入?
【发布时间】:2021-09-08 21:02:43
【问题描述】:

我有一个有点棘手的情况,主类(A 类)注入一个依赖项(B 类),然后在 A 类的一个方法中,它将调用委托给 B 类。

到目前为止,这听起来一点也不棘手,但这里有一个转折点:由于类 B 自动注入到类 A 中,它没有获得正确构造自身所需的参数。让我告诉你我在说什么:

class A {

   @Inject // inject object B
   public A(B objectB) {
      this.objectB = objectB
   }

   // delegate call to object B, however param1 is required in class B constructor in order to be constructed correctly
   public void example_method(String param1) {
    this.objectB.someMethod();
   }
}


class B {
   private C objectC;
   // class B needs param1 in order to create object C, so param1 has to be passed at the creation time
   public B(String param1) {
        objectC = new C(param1);
   }

   public void someMethod() {
    objectC.someOtherMethod();
   }

  public void someMethod2() {
    objectC.someOtherMethod2();
   }

}

我希望你能在这里看到这个问题:因为 B 类被 Guice 注入到 A 类中,所以它无法访问 param1,而 param1 只能传递给 A 类方法之一。从某种意义上说,B 类是在没有所需数据的情况下过早创建的。

有没有办法构造代码,以便在调用类 A 的 example_method() 之后延迟类 B 的构造?如果这不可能,你将如何重构它,记住我需要直接在 B 类的构造函数中构造 C 类,因为它将被 B 类中的许多不同方法调用。

【问题讨论】:

  • 这能回答你的问题吗? Guice: How to do late binding?
  • 问题在于我看不到如何将参数传递给提供者。只有方法 get() 不接受任何东西,所以我不能将任何东西从 A 类传递给 B 类的提供者,还是我弄错了? @aksappy

标签: java dependency-injection guice


【解决方案1】:

使用工厂。

不是将 B 对象注入 A 对象,而是向 A 注入创建 B 对象的工厂。

示例,没有任何JSR-330 语义:

public class FactoryExample {

    static class A {
        BFactory bFactory;

        A(BFactory bFactory) {
            this.bFactory = bFactory;
        }

        public void example_method(String param1) {
            B b = bFactory.createB(param1);
            b.someMethod();
        }
    }

    static class BFactory {
        B createB(String param1) {
            return new B(param1);
        }
    }

    static class B {
        String param1;

        B(String param1) {
            this.param1 = param1;
        }

        void someMethod() {
            System.out.println("someMethod");
        }
    }
}

B对象的创建可能不止一个String参数,而且必须注入。

解决方案:Guice - AssistedInject

或者更好:StackOverflow: Guice - How to use AssistedInject

所以你最终会得到这样的结果:

public class FactoryExample {

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(A.class);
                bind(X.class);
                install(new FactoryModuleBuilder().implement(B.class, B.class)
                        .build(BFactory.class));
            }
        });

        injector.getInstance(A.class).example_method("Michael Jackson is alive");
    }

    public static class A {
        BFactory bFactory;

        @Inject
        A(BFactory bFactory) {
            this.bFactory = bFactory;
        }

        public void example_method(String param1) {
            B b = bFactory.createB(param1);
            b.someMethod();
        }
    }

    public static interface BFactory {
        B createB(String parameter);
    }

    public static class X {

    }

    public static class B {
        String param1;
        X x;

        //X is injected by Guice
        //param1 is injected by the factory
        @Inject
        B(X x, @Assisted String param1) {
            this.x = x;
            this.param1 = param1;
        }

        void someMethod() {
            System.out.println("someMethod: " + param1);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-07-03
    • 1970-01-01
    • 2016-07-31
    • 2012-04-12
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多