8

你如何初始化这个:

class A {
    final B b;

    A(B b) {
        this.b = b;
    }
}

class B {
    final A a;

    B(A a) {
        this.a = a;
    }
}

DI框架,反射,更好的设计?

动机和用例(添加)

我的特殊用例是简化A' 和B' 子类中的字段访问。因此,我将它们注入以通过派生类中的字段简短地引用它们,而无需在每个子类中显式声明。

还有一个关于 DI 的建议,即对象最好是不可变的:Guice best practice and anti-patterns

4

3 回答 3

6

您可以使用工厂方法

class A {
    final B b;

    A(B b) {
        this.b = b;
    }
}

abstract class B {
    final A a;

    B() {
        this.a = constructA();
    }

    protected abstract A constructA();
}

public class C {
    public static void main(String []args){
        new B(){
            protected A constructA(){
                return new A(this);
            }
        };
    }
}
于 2013-11-06T10:26:15.633 回答
1

虽然它可能看起来很脏,但我更喜欢将其中一个final引用替换为Supplier(如一个 inGuavaJava 8),如:

class A {
    final Supplier<B> b;

    A(Supplier<B> b) {
        this.b = b;
    }

    // keeping this constructor just for usability's sake
    A(B b) {
        this.b = ofInstance(b); // using Guava's Suppliers.ofInstance here
    }
}

class B {
    final A a;

    B(A a) {
        this.a = a;
    }
}

public static void main(String[] args) {
    // using MutableSupplier.create() static factory method
    MutableSupplier<B> bRef = create();
    A a = new A(bRef);
    B b = bRef.set(new B(a));
}

whereMutableSupplier看起来像下面这样:

import com.google.common.base.Supplier;

public class MutableSupplier<T> implements Supplier<T> {

    private boolean valueWasSet;

    private T value;

    private MutableSupplier() {
    }

    @Override
    public T get() {
        if (!valueWasSet) {
            throw new NullPointerException("Value has not been set yet");
        }
        return value;
    }

    public T set(final T value) {
        if (valueWasSet) {
            throw new IllegalStateException("Value has already been set and should not be reset");
        }
        this.value = value;
        this.valueWasSet = true;
        return value;
    }

    public static <T> MutableSupplier<T> create() {
        return new MutableSupplier<T>();
    }

}

我知道MutableSupplier' 的可变性对于不变性爱好者来说看起来超级丑陋,但我发现在这种情况下使用它或多或少是可以接受的 :)

于 2013-11-07T12:06:19.133 回答
0

您所拥有的是循环依赖。我能想到的唯一方法是不要将字段声明为 final 并使用 setter 注入而不是构造函数注入来注入依赖项。

A a = new A();
B b = new B();

a.setB(b);
b.setA(a);
于 2013-11-06T10:23:25.453 回答