使用 Google Guice 注入 java 属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9772557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Google Guice to inject java properties
提问by markus
I want to use google guice to make properties available in all classes of my application. I defined a Module which loads and binds the properties file Test.properties.
我想使用 google guice 使属性在我的应用程序的所有类中可用。我定义了一个加载和绑定属性文件Test.properties的模块。
Property1=TEST
Property2=25
package com.test;
包 com.test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
public class TestConfiguration extends AbstractModule {
@Override
protected void configure() {
Properties properties = new Properties();
try {
properties.load(new FileReader("Test.properties"));
Names.bindProperties(binder(), properties);
} catch (FileNotFoundException e) {
System.out.println("The configuration file Test.properties can not be found");
} catch (IOException e) {
System.out.println("I/O Exception during loading configuration");
}
}
}
I'm using a main class where I create a injector to inject the properties.
我正在使用一个主类,我在其中创建了一个注入器来注入属性。
package com.test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Test {
public static void main(String[] args) {
TestConfiguration config = new TestConfiguration();
Injector injector = Guice.createInjector(config);
TestImpl test = injector.getInstance(TestImpl.class);
}
}
package com.test;
import com.google.inject.Inject;
import com.google.inject.name.Named;
public class TestImpl {
private final String property1;
private final Integer property2;
@Inject
public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2) {
System.out.println("Hello World");
this.property1 = property1;
this.property2 = property2;
System.out.println(property1);
System.out.println(property2);
}
}
Now my question. If my TestImpl creates other classes where I also need to inject properties, and those classes also need to inject properties what is the correct way to do this?
现在我的问题。如果我的 TestImpl 创建了我还需要注入属性的其他类,而这些类也需要注入属性,那么正确的方法是什么?
Pass the injector to all subclasses and then use injector.getInstance(...) to create the subclasses?
Instanciate a new injector like
TestConfiguration config = new TestConfiguration(); Injector injector = Guice.createInjector(config); TestImpl test = injector.getInstance(TestImpl.class);
将注入器传递给所有子类,然后使用 injector.getInstance(...) 来创建子类?
实例化一个新的注入器,如
TestConfiguration config = new TestConfiguration(); Injector injector = Guice.createInjector(config); TestImpl test = injector.getInstance(TestImpl.class);
in all nested classes?
在所有嵌套类中?
- Is there an other approach to make the properties available in all classes?
- 是否有其他方法可以使属性在所有类中可用?
采纳答案by Pierre-Henri
Pass the injector to all subclasses and then use injector.getInstance(...) to create the subclasses?
将注入器传递给所有子类,然后使用 injector.getInstance(...) 来创建子类?
no, by doing this you are defeating the purpose of the dependency injectionpattern and also coupling all your implementation to Guice. Your implementations should not interact at all with guice, except through the (now standardized) annotations.
不,通过这样做,您会破坏依赖注入模式的目的,并且还将您的所有实现都耦合到 Guice。您的实现根本不应该与 guice 交互,除非通过(现在标准化的)注释。
Instanciate a new injector like
TestConfiguration config = new TestConfiguration(); Injector injector = Guice.createInjector(config); TestImpl test = injector.getInstance(TestImpl.class);
in all nested classes?
实例化一个新的注入器,如
TestConfiguration config = new TestConfiguration(); Injector injector = Guice.createInjector(config); TestImpl test = injector.getInstance(TestImpl.class);
在所有嵌套类中?
no, and this is even worse cause you will end up with multiple injectors, hence multiple contexts which will prevent a proper usage of the scopes.
不,这更糟糕,因为您最终将使用多个注入器,因此多个上下文将阻止正确使用scopes。
Ideally, you should only use the injector during the bootstrapping of your application. Of course the way to bootstrap it will largely depend of the application.
理想情况下,您应该只在应用程序引导期间使用注入器。当然,引导它的方式在很大程度上取决于应用程序。
Is there an other approach to make the properties available in all classes?
是否有其他方法可以使属性在所有类中可用?
The properties could be injected the same way you did for TestImpl. If you want TestImpl to use let say a service which also needs some properties (or other services), just let Guice inject it to TestImpl. Guice is taking care of all the instantiation/wiring. You should only tell Guice "how to proceed", by using the binder, when Guice cannot figure this out itself :
可以按照与 TestImpl 相同的方式注入属性。如果你想让 TestImpl 使用让我们说一个也需要一些属性(或其他服务)的服务,只需让 Guice 将它注入到 TestImpl 中。Guice 负责所有的实例化/接线。当 Guice 自己无法弄清楚时,您应该只告诉 Guice“如何进行”,通过使用活页夹:
public class TestImpl {
private final String property1;
private final Integer property2;
private final IService service;
@Inject
public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2, IService service) {
this.property1 = property1;
this.property2 = property2;
this.service= service;
}
}
}
回答by Jan Galinski
"Now my question. If my TestImpl creates other classes where I also need to inject properties, and those classes also need to inject properties what is the correct way to do this?"
“现在我的问题。如果我的 TestImpl 创建了其他类,我也需要注入属性,而这些类也需要注入属性,那么正确的方法是什么?”
Rule of thumb: avoid the use of "new" Unless it is absolutely necessary, dont let your Impl Class "create other classes". Instead, tell your TestImpl that when created with guice, it should get the required instances injected.
经验法则:避免使用“new”除非绝对必要,否则不要让您的 Impl 类“创建其他类”。相反,告诉您的 TestImpl 使用 guice 创建时,它应该注入所需的实例。
回答by EIIPII
Library "Governator" provide a configuration mapping feature for guice injection. The approach is different, but load from properties files is available.
库“Governator”为 guice 注入提供了配置映射功能。方法不同,但可以从属性文件加载。
https://github.com/Netflix/governator/wiki/Configuration-Mapping
https://github.com/Netflix/governator/wiki/Configuration-Mapping
回答by Stranger in the Q
Usage example: At first we have a properties file 'config.properties':
用法示例:首先我们有一个属性文件“config.properties”:
test.key=test value
And we want to inject this value like this:
我们想像这样注入这个值:
@Inject
@Config( Property.TEST_KEY )
private String injectedValue;
We need to load contents of file 'config.properties' into java.util.Properties and pass it to Config module:
我们需要将文件 'config.properties' 的内容加载到 java.util.Properties 并将其传递给 Config 模块:
Properties props = new Properties();
props.load(...);
Module configModule = new ConfigModule( props, Property.values() ); ... and injecting:
模块 configModule = new ConfigModule( props, Property.values() ); ...并注入:
Injector injector = Guice.createInjector( configModule );
TestClass testClass = injector.getInstance( TestClass.class );
String injectedValue = testClass.getInjectedValue();
injected value will be 'test value'...
注入的值将是“测试值”...
回答by Yves Galante
The library Guice configurationcan inject for you values from Properties or JSON files to your services.
库Guice 配置可以将属性或 JSON 文件中的值注入到您的服务中。
You can inject from the file application.propertiesto your service as :
您可以从文件application.properties注入您的服务:
@BindConfig(value = "application", syntax = PROPERTIES)
public class Service {
@InjectConfig
private int port;
@InjectConfig
private String url;
@InjectConfig
private Optional<Integer> timeout;
}
You must simply install the modules ConfigurationModule
您必须简单地安装模块ConfigurationModule
public class GuiceModule extends AbstractModule {
@Override
protected void configure() {
install(ConfigurationModule.create());
requestInjection(Service.class);
}
}