Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice - How to share the same Singleton instance through multiple injectors/modules

In guice, the @Singleton scope does not refer to the Singleton pattern.

According to the "Dependency Injection" book of "Dhanji" :

Very simply, a singleton’s context is the injector itself. The life of a singleton is tied to the life of the injector (as in figure 5.8). Therefore, only one instance of a singleton is ever created per injector. It is important to emphasize this last point, since it is possible for multiple injectors to exist in the same application. In such a scenario, each injector will hold a different instance of the singleton-scoped object.

Singleton scope

Is it possible to share the same Singleton instance through multiple modules and multiple injectors ?

like image 984
Sandro Munda Avatar asked Dec 02 '11 12:12

Sandro Munda


People also ask

Does dependency injection use singleton?

The heuristic to determine whether you need to introduce a singleton is simple. If a dependency cross-cuts most of your classes and/or several layers in your application, extract it using the Singleton pattern. Otherwise, use the standard Dependency Injection technique.

What does @inject do Guice?

Note that the only Guice-specific code in the above is the @Inject annotation. This annotation marks an injection point. Guice will attempt to reconcile the dependencies implied by the annotated constructor, method, or field.

What is singleton in Guice?

Guice returns a new instance every time when it supplies a value as its default behaviour. It is configurable via scopes. Following are the scopes that Guice supports: @Singleton - Single instance for lifetime of the application.

What is Guice dependency?

Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 8 and above, brought to you by Google.


2 Answers

You can use Injector.createChildInjector:

// bind shared singletons here
Injector parent = Guice.createInjector(new MySharedSingletonsModule());
// create new injectors that share singletons
Injector i1 = parent.createChildInjector(new MyModule1(), new MyModule2());
Injector i2 = parent.createChildInjector(new MyModule3(), new MyModule4());
// now injectors i1 and i2 share all the bindings of parent
like image 177
sanjary Avatar answered Sep 30 '22 03:09

sanjary


I don't see why you need that, but if you really want, it's possible:

package stackoverflow;

import javax.inject.Inject;
import javax.inject.Singleton;

import junit.framework.Assert;

import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;

public class InjectorSingletonTest {

    static class ModuleOne extends AbstractModule {
        @Override
        protected void configure() {
            bind(MySingleton.class);
        }
    }

    static class ModuleTwo extends AbstractModule {
        final MySingleton singleton;

        @Inject
        ModuleTwo(MySingleton singleton){
            this.singleton = singleton;
        }

        @Override
        protected void configure() {
            bind(MySingleton.class).toInstance(singleton);
        }
    }

    @Singleton
    static class MySingleton { }

    @Test
    public void test(){
        Injector injectorOne = Guice.createInjector(new ModuleOne());

        Module moduleTwo = injectorOne.getInstance(ModuleTwo.class);
        Injector injectorTwo = Guice.createInjector(moduleTwo);

        MySingleton singletonFromInjectorOne =
                injectorOne.getInstance(MySingleton.class);

        MySingleton singletonFromInjectorTwo =
                injectorTwo.getInstance(MySingleton.class);

        Assert.assertSame(singletonFromInjectorOne, singletonFromInjectorTwo);
    }
}
like image 33
eiden Avatar answered Sep 30 '22 03:09

eiden