Вот упрощенная версия моих потребностей.
У меня есть программа, в которой каждый объект 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. Так что это одиночный объект, но для ограниченной области программы (фактически, ограниченной области структуры данных).
(2) Я не против решениякоторый использует метод (установщик) - или инъекцию поля.
(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);
}
}