2016-07-26 25 views
1

我的總體目標是從屬性文件加載屬性,然後將這些屬性注入到對象中。我也想用這些屬性來實例化使用Guice的某些單例類。我的單身類看起來是這樣的:我如何從Guice中獲得配置了運行時參數的單例?

public class MainStore(){ 
    private String hostname; 

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

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

我嘗試使用此提供實例化一個單例:

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

我configurationModule是加載在運行時指定的屬性文件中的配置模塊:

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; 
    } 
} 

而且我example.properties文件包含:

hostname = testHostName 

後來,當我需要我使用MainStore單:

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

這是往下走正確的道路?我應該以完全不同的方式做這件事嗎?爲什麼我的MainStore不能打印出正確的主機名?

+0

提供者不設置主機名屬性的單身人士。爲什麼你首先需要提供商?由於guice不處理您的班級建設,因此不會設置該屬性。您必須將您的財產注入您的提供者實施並在創建之後進行設置。此外,並糾正我,如果我錯了,但您的提供程序不會創建單身人士,而是每次創建一個新的實例。 – pandaadb

+0

我想用提供者爲我提供一個單例。我不知道該怎麼做,所以我可能做錯了。此外,我認爲Guice會將Injected屬性級聯到提供程序中創建的所有類中。但這種方法可能完全錯誤。 – Grammin

+0

不,guice不會那麼做,因爲你是創造物體的人,而不是guice。您的主機名打印錯誤的原因也是因爲您在構造函數中打印了它,但是您注入了一個方法。方法注入只能在構造對象後發生(因爲沒有其他方法可以調用)。如果你想要一個單身人士,那麼你可以在Singleton範圍內綁定,並簡單地注入構造函數的屬性(就像你做的方法)。把你的財產想象成一個名字字符串對象,你可以注入任何Guice Managed類。 – pandaadb

回答

2

我已經寫了一個小例子,演示如何綁定一個單例,如何注入一個屬性等。

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); 

    } 
} 

配置方法現在負責告訴guice我的Test類是一個單例。

它打印正確的主機名(屬性測試),因爲我注入構造函數並設置屬性。

您也可以使用提供程序完成此操作,但是您必須手動創建對象。在我而言,這應該是這樣的:

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; 
     } 

    } 

綁定,然後將這個樣子:

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

這是你想要的嗎?

乾杯,

阿圖爾

編輯:

我做了一些測試,發現此要注意:

可以綁定一個供應商作爲一個單身:

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

這樣你就不需要自己處理單件創建:

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; 
     } 

    } 

上面的代碼將創建對象X.

+0

這絕對有幫助!謝謝!有什麼辦法可以從TestModule中移除Singleton.class並將其放入TestProvider中。我想從屬性文件中的任何InjectProperties中使用TestModule,並在需要它們的地方使用不同的提供程序。 – Grammin

+0

我不知道我明白。您可以將提供程序綁定爲單例,然後它將返回第一次創建的實例。詳情請參閱我的更新。不同提供商的含義是什麼?您是否使用相同的模塊創建多個注射器? – pandaadb

+0

這回答我的問題,我想。非常感謝您的幫助。最後一個注意事項,如果我不必將TestProvider耦合到TestModule,那將非常棒。 – Grammin

相關問題