Guice inject single instance into multiple objects without using @Singleton
cyclic-dependency, guice, java
Solution
You should use a provider
public class StoreProvider implements Provider<Store> {
@Inject
private Boss boss ;
public Store get() {
return new Store(boss, boss.getClerk().getCustomerLine());
}
}
And then bind it in your module
`bind(Store.class).toProvider(StoreProvider.class);`
Problem
I was reading the Guice documentation, and came across a section labeled Eliminate the Cycle (Recommended) which peaked my interest because it's exactly the issue that led me to the documentation today. Basically, to eliminate cyclic dependencies, you "extract the Dependency Case into a separate class." Okay, nothing new there. So, in the example, we have. ``` public class Store { private final Boss boss; private final CustomerLine line; //... @Inject public Store(Boss boss, CustomerLine line) { this.boss = boss; this.line = line; //... } public void incomingCustomer(Customer customer) { line.add(customer); } } public class Boss { private final Clerk clerk; @Inject public Boss(Clerk clerk) { this.clerk = clerk; } } public class Clerk { private final CustomerLine line; @Inject Clerk(CustomerLine line) { this.line = line; } void doSale() { Customer sucker = line.getNextCustomer(); //... } } ``` You have a `Store` and a `Clerk` and each need to have a reference to a single instance of `CustomerLine`. No problems with this concept, and easily doable with classic Dependency Injection: ``` CustomerLine customerLine = new CustomerLine(); Clerk clerk = new Clerk(customerLine); Boss boss = new Boss(clerk); Store store = new Store(boss, customerLine); ``` That's easy enough, but now, I need to do this with Guice injection. Thus, my issue is with implementing the following: you may want to make sure that the Store and Clerk both use the same CustomerLine instance. Yes, that is exactly what I want to do. But how do I do that in a Guice module? ``` public class MyModule extends AbstractModule implements Module { @Override protected void configure() { //Side Question: Do I need to do this if there if Boss.class is the implementation? bind(Boss.class); bind(CustomerLine.class).to(DefaultCustomerLine.class); //impl } } ``` I create an injector with my module: ``` Injector injector = Guice.createInjector(new MyModule()); ``` Now, I want an instance of `Store`: ``` Store store = injector.getInstance(Store.class); ``` This will inject a new instance of `CustomerLine` and `Boss` into this instance of `Store`. `Boss`, however, gets an instance of `Clerk` which also gets injected an instance of `CustomerLine`. At this point, it would be a new instance, unique from the instance injected into `Store`. Question Revisited - How can `Store` and `Clerk` share the same instance in this sequence, without using `@Singleton`? Please, let me know if more information is required, or this question isn't stated clearly enough and I will be sure to revise.