简体   繁体   中英

Creating Guice singleton that's not tied to an Injector

Our project is setup as follows:

1) Main module: Contains a driver program which starts a Spark streaming server. It has its own Guice injector.

2) When message comes in, it goes to another module, which creates it's own Guice injector.

3) This module uses classes in other modules which themselves use dependent modules. Each of these modules creates its own Guice injector so that it can work independently, tested individually etc.

Here's a problem: Now we need a Singleton, but an object created as @Singleton is bound to an injector (Not to a ClassLoader), so when the Injector goes away the object goes away.

Questions:

1) Is our architecture bad? Should we not be creating an injector in every module?

2) How do we create a Singleton that will remain in a ClassLoader even when injector goes away?

BTW, we use Netflix Governator on top on Guice.

Note: Answer for the question which is supposedly duplicate of this question doesn't answer how a 'single' injector created on the top level module can be passed to the sub-modules. Also, if the sub-modules themselves don't have an injector, can we write standalone unit tests for them?

An idea for question 2 would be to use a provider that you can bind in all your different Modules. This provider would access a singleton that that exists 'outside' of Guice.

I have crafted a simple example where I provide access to a static field. You can change that to use the implementation of the Singleton pattern that suits your needs.

public class SingletonProvider implements Provider<TheSingleton> {

    private static final TheSingleton instance  = new TheSingleton();
    @Override
    public TheSingleton get() {
        return instance;
    }
}

Then we bind this to our different modules

public class Module1 extends AbstractModule {

    @Override
    protected void configure() {
       bind(TheSingleton.class).toProvider( SingletonProvider.class);
    }
}
public class Module2 extends AbstractModule {

    @Override
    protected void configure() {
       bind(TheSingleton.class).toProvider( SingletonProvider.class);
    }
}

And then I create two different injectors that return this same instance

public class Test {
    public static void main(String[] args) {
        Injector injector1 = Guice.createInjector(new Module1());

        TheSingleton instance = injector1.getInstance(TheSingleton.class);
        System.out.println("instance = " + instance);

        Injector injector2 = Guice.createInjector(new Module2());
        TheSingleton instance2 = injector2.getInstance(TheSingleton.class);
        System.out.println("instance2 = " + instance2);


    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM