How can I a get singleton from Guice that's configured with runtime parameters?

倾然丶 夕夏残阳落幕 提交于 2019-12-24 06:49:43

问题


My overall goal is to load properties from a properties file and then inject those properties into my objects. I would also like to use those properties to instantiate certain singleton classes using Guice. My singleton class looks like this:

public class MainStore(){
  private String hostname;

  @Inject
  public void setHostname(@Named("hostname") String hostname){
    this.hostname = hostname;
  }

  public MainStore(){
    System.out.println(hostname);
  }
}

I'm trying to instantiate a singleton using this provider:

public class MainStoreProvider implements Provider<MainStore> {
  @Override
  public MainStore get(){
    MainStore mainStore = new MainStore();
    return mainStore;
  }
}

My configurationModule is a module that loads a configuration from a property file specified at runtime:

public class ConfigurationModule extends AbstractModule {
  @Override
  protected void configure(){
    Properties properties = loadProperties();
    Names.bindProperties(binder(), properties);
  }

  private static Properties loadProperties() {
    String resourceFileName = "example.properties";
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    InputStream inputStream = classLoader.getResourceAsStream(resourceFileName);

    Properties properties = new Properties();
    properties.load(inputStream);

    return properties;
  }
}

And my example.properties files contains:

hostname = testHostName

Then when I need the MainStore singleton I'm using:

Injector injector = Guice.createInjector(new ConfigurationModule());
MainStoreProvider mainStoreProvider = injector.getInstance(MainStoreProvider.class);
MainStore mainStore = mainStoreProvider.get();  //MainClass singleton

Is this the right path to go down? Should I be doing this a completely different way? Why does my MainStore not print out the correct hostname?


回答1:


I have written up a small example that demonstrates how to bind a Singleton, how to inject a property and so on.

public class TestModule extends AbstractModule {

    @Override
    protected void configure() {
        Properties p = new Properties();
        p.setProperty("my.test.string", "Some String"); // works with boolean, int, double ....
        Names.bindProperties(binder(),p);
        bind(X.class).to(Test.class).in(Singleton.class); // This is now a guice managed singleton
    }

    public interface X {

    }

    public static class Test implements X {

        private String test;

        @Inject
        public Test(@Named("my.test.string") String test) {
            this.test = test;
            System.out.println(this.test);
        }

        public String getTest() {
            return test;
        }
    }

    public static void main(String[] args) {

        Injector createInjector = Guice.createInjector(new TestModule());
        Test instance = createInjector.getInstance(Test.class);

    }
}

The configure method is now responsible to tell guice that my Test class is a singleton.

It prints the correct hostname (property test) because I inject the constructor and set the property.

You can do this with a provider as well, however you will then have to create your objects manually. In my case, this would look like this:

public static class TestProvider implements Provider<X> {

        private String test;

        private X instance;

        public TestProvider(@Named("my.test.string") String test) {
            this.test = test;
        }

        @Override
        public X get() {
            if(instance == null) {
                instance = new Test(test);
            }
            return instance;
        }

    }

Binding will then look like this:

bind(X.class).toProvider(TestProvider.class);

Is this what you wanted?

Cheers,

Artur

Edit:

I did some test and found this to note:

You can bind a provider as a singleton:

bind(X.class).toProvider(TestProvider.class).in(Singleton.class);

That way you do not need to handle singleton creation yourself:

public static class TestProvider implements Provider<X> {

        private String test;

        private X instance;

        @Inject
        public TestProvider(@Named("my.test.string") String test) {
            this.test = test;
        }

        @Override
        public X get() {
            return instance;
        }

    }

The above code will create singletons of the object X.



来源:https://stackoverflow.com/questions/38589940/how-can-i-a-get-singleton-from-guice-thats-configured-with-runtime-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!