Вот упрощенная версия моих потребностей.
У меня есть программа, где каждый объект B имеет свой собственный объект C и D, вводимый через Guice. Кроме того, объект A вводится в каждый объект C и D.
Что я хочу: для каждого объекта B его объекты C и D будут вставляться одним и тем же объектом A.
[Edit-Start]
(1) Guice поддерживает режимы "singleton" и "prototype". Тем не менее, мне нужно что-то среднее: мне нужно, чтобы A был одиночным WRT для данного объекта B (так что C и D, введенные в объект B, будут совместно использовать объект A). Для другого объекта B, я хочу другого A. Так что это singleton, но для ограниченного объема программы (на самом деле, ограниченная область структуры данных).
(2) Я не против решения, которое использует метод (setter) - или инъекцию поля.
(3) Я пытался, несколько раз, добиваться этого, и всегда считалось, что мне нужно реализовать какую-то обычную вещь из контейнера DI, чтобы сделать эту работу, но она никогда не срабатывала. Таким образом, я ищу подробное решение (а не только "ручное размахивание" )
[Edit-End]
В частности, я хочу, чтобы выход программы (ниже) был:
Created C0 with [A0]
Created D0 with [A0]
Created B0 with [C0, D0]
Created C1 with [A1]
Created D1 with [A1]
Created B1 with [C1, D1]
Где он в настоящее время производит следующий вывод:
Created C0 with [A0]
Created D0 with [A1] <-- Should be A0
Created B0 with [C0, D0]
Created C1 with [A2] <-- Should be A1
Created D1 with [A3] <-- Should be A1
Created B1 with [C1, D1]
Я ожидаю, что контейнеры DI разрешат такую настройку, но до сих пор мне не удавалось найти решение. Ниже приведен мой код на основе Guice, но приветствуется решение на основе Spring (или другого контейнера на основе DI).
import java.util.Arrays;
import com.google.inject.*;
public class Main {
public static class Super {
private static Map<Class<?>,Integer> map = new HashMap<Class<?>,Integer>();
private Integer value;
public Super(Object... args) {
value = map.get(getClass());
value = value == null ? 0 : ++value;
map.put(getClass(), value);
if(args.length > 0)
System.out.println("Created " + this + " with " + Arrays.toString(args));
}
@Override
public final String toString() {
return "" + getClass().getSimpleName().charAt(0) + value;
}
}
public interface A { }
public static class AImpl extends Super implements A { }
public interface B { }
public static class BImpl extends Super implements B {
@Inject public BImpl(C c, D d) { super(c,d); }
}
public interface C { }
public static class CImpl extends Super implements C {
@Inject public CImpl(A a) { super(a); }
}
public interface D { }
public static class DImpl extends Super implements D {
@Inject public DImpl(A a) { super(a); }
}
public static class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(A.class).to(AImpl.class);
bind(B.class).to(BImpl.class);
bind(C.class).to(CImpl.class);
bind(D.class).to(DImpl.class);
}
}
public static void main(String[] args) {
Injector inj = Guice.createInjector(new MyModule());
inj.getInstance(B.class);
inj.getInstance(B.class);
}
}