如何从配置了运行时参数的 Guice 中获取单例?
How can I a get singleton from Guice that's configured with runtime parameters?
我的总体目标是从属性文件加载属性,然后将这些属性注入到我的对象中。我还想使用这些属性使用 Guice 实例化某些单例 classes。我的单身人士 class 看起来像这样:
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 没有打印出正确的主机名?
我写了一个小例子来演示如何绑定单例,如何注入 属性 等等。
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);
}
}
configure 方法现在负责告诉 guice 我的测试 class 是单例。
它打印出正确的主机名(属性 测试),因为我注入了构造函数并设置了 属性。
您也可以使用提供程序执行此操作,但是您必须手动创建对象。在我的例子中,这看起来像这样:
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 的单例。
我的总体目标是从属性文件加载属性,然后将这些属性注入到我的对象中。我还想使用这些属性使用 Guice 实例化某些单例 classes。我的单身人士 class 看起来像这样:
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 没有打印出正确的主机名?
我写了一个小例子来演示如何绑定单例,如何注入 属性 等等。
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);
}
}
configure 方法现在负责告诉 guice 我的测试 class 是单例。
它打印出正确的主机名(属性 测试),因为我注入了构造函数并设置了 属性。
您也可以使用提供程序执行此操作,但是您必须手动创建对象。在我的例子中,这看起来像这样:
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 的单例。