google / google/guice

Problem with singletons instantiation for child injectors

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

Description

As @Crunkle stated in https://github.com/google/guice/issues/1084#issuecomment-308415419, the behaviour in case when there's an explicit singleton binding in one child injector but not the other is quite unexpected. We encountered this bug in production and it took a lot of research to isolate the issue.

> The following test fails, yet follows your wording: the first child's instance should be different whilst the second and third are shared. It is true that they are both singletons in their own scopes, but they are not equivalent instances and definitely not shared.
>
> ```java
> public class GuiceTest {
>
> @Test
> public void testChildren() {
> Injector root = Guice.createInjector();
>
> Injector manualChild = root.createChildInjector(new AbstractModule() {
>
> @Override
> protected void configure() {
> this.bind(MySingleton.class).toInstance(new MySingleton());
> }
> });
>
> // Pass
> MySingleton nonJIT = manualChild.getInstance(MySingleton.class);
>
> // Fail
> Assert.assertEquals(
> root.createChildInjector().getInstance(MySingleton.class),
> root.createChildInjector().getInstance(MySingleton.class)
> );
> }
> }
> ```

Thus @lukesandberg 's words
>in the second and third child MySingleton is a jit binding. for child injectors we intentionally try to resolve jit bindings in parents first. so both secondChild and thirdChild will ask the root for the binding and thus share the singleton.

are incorrect and #1084 was closed incorrecly. This issue should be fixed.

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.