google / google/guice

Whether circular dependencies work depends on the order objects are retrieved from the injector

Open
#970 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

For example:

``` java
class A {
@Inject
A(B b) {
}
}

class B {
@Inject
A a;
}

class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(A.class).in(Singleton.class);
bind(B.class).in(Singleton.class);
}
}

public class FooTest {
@Test
public void testAFirst() {
// Fails
Guice.createInjector(new MyModule()).getInstance(A.class);
}

@Test
public void testBFirst() {
// Passes
Guice.createInjector(new MyModule()).getInstance(B.class);
}

@Test
public void testProduction() {
// Fails for me, probably not deterministic?
Guice.createInjector(Stage.PRODUCTION, new MyModule());
}
}
```

I think I understand why this happens, but I don't think it's particularly desirable. In fact, when it does "work," we're still passing a partially-initialized `B` instance to `A`'s constructor, which could be problematic if it tries to _use_ `B` instead of just storing it in a field.

My proposed resolution is a new flag `binder().disableCircularDependencies()` that completely disallows dependency cycles (unless broken by a `Provider`). Or possibly `binder().disableCircularClassDependencies()` if we want the option to allow circular dependencies through interfaces, since those work due to proxying.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.