【问题标题】:Java constructor with Guice injected fields along with non-injected fields带有 Guice 注入字段和非注入字段的 Java 构造函数
【发布时间】:2013-11-13 02:24:00
【问题描述】:

我有一个类,它有一个构造函数,其中所有参数都由 GUICE 注入。

Public class Order {

    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;

    @Inject
    public order(ClassOne classOneObj, ClassTwo classTwoObj){
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }
}

现在,我想再添加一个无法注入的字段(例如,int status)变量。

先用所有注入的参数创建一个对象,然后设置不能用setter方法注入的新字段,这是一个好习惯吗?

我想出了另一种方法,我创建了一个工厂类,如下所示:

public class OrderFactory {

    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;

    @Inject
    public order(ClassOne classOneObj, ClassTwo classTwoObj){
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }

   //getter methods for all the above variables

    public  ClassOne getclassOneObj(){
          return classOneObj;
    }
    ....

    public Order createOrder(int status) {
        return new Order(status, classOneObj, classTwoObj);
    }
}

那么新的 Order 类会是这样的

public class Order {

    int status
    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;


    public order(int status, ClassOne classOneObj, ClassTwo classTwoObj){
    this.status = status
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }

    //getter methods for all these member variables
}

现在要创建订单对象,我将首先创建一个 OrderFactory 对象,然后使用“createOrder”方法创建订单对象。

我最终要编写样板代码。不确定这是否是一个好习惯。如果这种方法是正确的或者有更好的方法来解决这个问题,有人可以提出建议吗?

我在 Google Guice 中阅读并发现有一个功能 @Assisted 可用于此类情况的辅助注射。但我发现这很复杂,无法说服自己是否应该在我的情况下这样做。

提前感谢您的任何建议或指导。

【问题讨论】:

  • 与 iluxa 相呼应,您对工厂的手动方法很好,尽管您可以以更短的方式使辅助注射工作。如果您想使用相同的 OrderFactory 创建许多不同的订单,我唯一要更改的手动注入是注入 Provder<ClassOne>Provider<ClassTwo>。否则,它看起来很棒。

标签: java constructor guice code-injection


【解决方案1】:

您通常会注入一些需要付出一些努力才能构建的东西。如果您只是注入一个 int 字段,最好只在对象上调用一个 setter 方法(其中注入了一些更复杂的依赖项)。此外,如果一个字段经常更改,正如一个名为“状态”的字段所暗示的那样,那么它也不是一个很好的注入候选者。

【讨论】:

  • 请尽可能避免使用二传手。如果有任何机会保持对象不可变及其所有字段final,请执行此操作。
  • +1 到 iluxa。不可变对象有a lot of benefits。我们都同意注入 status 是个坏主意,但 OP 的问题是让注入与 non-injected 构造函数参数共存,其中有许多有效的用例。
  • 是的,为 Google 工作会教你一两点关于 guice 的知识,不是吗... :-)
  • 我同意不变性,尤其是在多线程方面是最好的。在他的用例中,一个名为“状态”的字段似乎表明波动性,也许不是(特别是如果他为它提供了一个工厂)。如果该字段永远不会改变,请确保注入它。如果是这样,您想每次都创建一个新的吗? int 赋值是原子的,让它变得易变,你就可以开始了。
【解决方案2】:

您的工厂方法非常出色。请不要使用 setter:如果可以将字段设置为不可变,则它应该是不可变的,无论它是否“方便”实例化。

您可以采用的另一种方法是Assisted Injection,它可以解决这个确切的问题。这样,您只需定义工厂接口,Guice 就会神奇地为您提供其实现:

class Order {
  interface Factory {
    Order create(Status status);
  }

  @AssistedInject Order(
      ClassOne one, 
      ClassTwo two, 
      @Assisted Status status) {
  }
}

模块代码:

bind(Order.Factory.class).toProvider(
    FactoryProvider.newFactory(Order.Factory.class, Order.class));

然后客户端注入Factory 并像在您的示例中一样使用它。

【讨论】:

    猜你喜欢
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    相关资源
    最近更新 更多