I think that NamshubWriter's proposal isn't very guicy. I think that in Guice, a constructor should do exactly one thing: assign parameters into fields. If there's anything else you need to do, put it into a factory or a provider.
In this case, we'll want a provider for A. The provider could directly call new B(), but then we'd directly couple A to B, which is what we tried to avoid in the first place. So we indirect the creation of B over a factory, which guice can provide for us via assistedInject. This code runs and compiles fine, and completely decouples A and B.
In a realistic scenario, you'd need to hide A and B behind interfaces to take advantage of the separation.
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryProvider;
public class Try {
public static void main(String[] args) {
System.out.println(
Guice.createInjector(new MyModule()).getInstance(A.class)
);
}
}
class MyModule extends AbstractModule {
public void configure() {
bind(A.class).toProvider(AProvider.class);
bind(IBFactory.class).toProvider(
FactoryProvider.newFactory(IBFactory.class, B.class));
}
}
class A {
B b;
public void setB(B b) {
this.b = b;
}
}
class B {
A a;
@Inject
B(@Assisted A a) {
this.a = a;
}
}
class AProvider implements Provider<A> {
private final IBFactory bFactory;
@Inject
AProvider(IBFactory bFactory) {
this.bFactory = bFactory;
}
public A get() {
A a = new A();
a.setB(bFactory.create(a));
return a;
}
}
interface IBFactory {
public B create(A a);
}
I made an extended version of the circular dependency injection in Guice where A and B are hidden behind interfaces.