如果你有很多设置,不想为每个设置创建新的绑定注解,那么可以尝试将它们放在枚举中,并在通用绑定注解中使用该枚举。这可能是一个比较复杂的解决方案,但也可以节省你试图避免的样板代码。
通过这种方式,你可以匹配对象引用(便于IDE),而不是字符串(慢且脆弱),并且仍然只创建一个绑定注解。
public enum Config {
DB_NAME("db_name"),
DB_HOST("db_host_name_specified_in_file"),
SOME_NUMBER("some_number"),
;
private final String propertyName;
private Config(String propertyName) {
this.propertyName = propertyName;
}
public String getPropertyName() {
return propertyName;
}
public InjectConfig annotation() {
return new InjectConfig() {
@Override public Class<? extends Annotation> annotationType() {
return InjectConfig.class;
}
@Override public Config value() {
return Config.this;
}
@Override public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof InjectConfig)) {
return false;
}
return value() == ((InjectConfig) obj).value();
}
@Override public int hashCode() {
return (127 * "value".hashCode()) ^ value().hashCode();
}
};
}
@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public static @interface InjectConfig {
Config value();
}
}
现在您可以通过循环迭代每个并绑定它们:
public class YourModule extend AbstractModule {
@Override public void configure() {
Provider<Settings> settingsProvider = binder().getProvider(Settings.class);
for (Config config : Config.values()) {
String propertyName = config.getPropertyName();
bind(String.class).annotatedWith(config.annotation()).toProvider(
new GetValueFromSettingsProvider(settingsProvider, propertyName));
}
}
}
直接注入你所需的内容:
YourClass(@InjectConfig(DB_USER) String user,
@InjectConfig(SOME_NUMBER) int number) { }
我没有测试过这个,但据我所知它应该可以工作。考虑到您的特定设置用例,您可能需要调整您编写的GetValueFromSettingsProvider
方法,或在枚举中编写可重写的getConfigValueFromSettings
方法。请记住,无论如何,您仍然需要存储(枚举键,文件中的属性名称,属性类型)三元组,而枚举似乎是以编程方式管理它的最佳方法。