我有一个应该从文件中读取配置参数的Java程序,如下所示:
java -jar myapp.jar --config config.txt ...
加载后,这些参数不会更改,并且程序中的任何类都应该可以访问这些参数。
是否可以从任何类访问这些参数而不将显式添加为构造函数和方法的参数?例如,我希望能够做到这一点:
public class Main {
public static void main(String[] args){
// This list should be visible by any class
List<String> CONFIGS= readMyConfigsFromFile(args[0]);
...
}
}
public class MyClass(){
public MyClass(){
String thisConf= CONFIGS.get(0); // Do something with this conf param taken from Main.
...
}
}
public class MyOtherClass(){
public MyOtherClass(){
String thisConf= CONFIGS.get(0); // Do something with this conf param taken from Main.
...
}
}
...
这有可能吗?这是一个明智的设置吗?如果没有,推荐的设计是什么?
(我已经阅读了类似的问题,但我仍然不确定在我描述的情况下是否以及如何可能)
答案 0 :(得分:2)
您可以使用Singleton模式。
为了对其进行建模,我假设您的配置中有2个字段:字符串和整数。
public class Config {
private static Config INSTANCE;
private final String field1;
private final int field2;
public Config(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
public String getField1() {
return field1;
}
public int getField2() {
return field2;
}
public static Config getInstance() {
if (INSTANCE == null) {
INSTANCE = loadInstance();
}
return INSTANCE;
}
private static Config loadInstance() {
// read your config from properties
String field1 = ...
int field2 = ...
return new Config(field1, field2);
}
}
然后在需要的任何地方使用Config.getInstance()
来获取该实例。
请注意,此实现存在一个缺陷:如果从不同的theads调用getInstance()
,可能会多次初始化。
如果只对初始化一次很重要,可以使用双重检查锁定https://en.wikipedia.org/wiki/Double-checked_locking来克服此缺陷。
答案 1 :(得分:1)
此解决方案与其他解决方案一样,需要模拟对象进行单元测试。但我认为这是最好的,因为它将参数封装在一个不可变对象中。这也使线程安全成为一个问题。如果您愿意,可以使用HashMap而不是数组来按键而不是索引来访问这些:
public class Main {
public static void main(String[] args){
new CONFIG(readMyConfigsFromFile(args[0]).toArray());
...
}
public static final class CONFIG {
private final String[] args;
private static final CONFIG instance;
private CONFIG(String[] args) {
this.args = args;
instance = this;
}
public static CONFIG getInstance() {
return CONFIG.instance;
}
public String[] getArgs(){
return Arrays.copy(this.args, this.args.length);
}
public String getArg(int index) {
return args[index];
}
}
获取参数:
Main.CONFIG.getArgs();
答案 2 :(得分:0)
“这有可能吗?”是的。你可以在java的静态帮助下轻松完成它。
public class Config {
private static final List<String> config = new ArrayList<String>();
public static void addConfig(String value){
config.add(value);
}
public static List<String> getConfig(){
return config;
}
}
要为配置添加值,您可以执行
public static void main(String[] args) {
//Read value from file here in some variable say configValue
Config.addConfig(configValue);
}
访问配置
public class MyOtherClass(){
public MyOtherClass(){
Config.getConfig().get(0); // Do something with this conf param taken from Main.
...
}
}
注意上面的代码不是线程安全的。您可以通过添加同步概念使其线程安全
现在“这是一个明智的设置吗?”。这取决于您的要求。正如您所提到的,这些值不会改变运行时,那么您可以使用它。但是我们需要强制执行这些值“不应该更改”,一旦初始化然后答案将是不同的,你应该使用像Singleton Pattern这样的东西并修改以确保你只能在构造对象时读取而不能写入。另请注意,使用静态方法,就像我建议的那样,测试变得非常困难。