Java: использование имен ключей из файла свойств без использования жестко закодированных строк в качестве ключей

Постановка задачи

У меня есть файл свойств, который доступен во всем моем проекте Java.

Пример содержимого моего .properties файл:

appName=MyApp
appType=TypeA

Допустим, у меня есть доступ к единственному свойству, appName, на протяжении всего моего проекта Java

props.getProperty("appName");

Я не хочу перебирать файл свойств, чтобы получить значение свойства; Я просто получаю одно значение свойства из файла свойств. Но мне не нравится тот факт, что мне нужно получить доступ к свойству, используя жестко закодированную строку, потому что это может привести к проблемам с обслуживанием (то есть к изменению всех экземпляров жестко закодированной строки).

Мой нынешний подход

В моем текущем подходе у меня есть служебный класс, который создает статические конечные переменные, представляющие имена ключей в файле свойств, а затем я использую эту переменную для доступа к значению свойства:

public static final String APP_NAME = "appName";
...
props.getProperty(APP_NAME);

Но это кажется излишним, потому что это избыточно, и все еще является потенциальной проблемой обслуживания. Ключ уже существует в файле свойств, и я снова объявляю их в своем служебном классе.

Есть ли более "необслуживаемый" способ доступа к имени ключа в моем коде при использовании методов get для доступа к значениям свойств?

3 ответа

Решение

Нет, вы делаете это правильно. И это на самом деле довольно не требует обслуживания.

Использование Java Enums будет немного предпочтительнее - т.е.

public class PropertiesWrapper {
   private final Properties props;
   ...
   public String get(MyEnum key) {  return props.get(key.toString());
}

Причина в том, что даже если вы сделаете эту String константой, вы никогда не сможете изменить ее, не перекомпилировав весь код, который использует константу, потому что компилятор заменит константу на "appName" во время компиляции.

Если вы используете перечисления и удаляете константу перечисления, код все равно будет нуждаться в перекомпиляции, но это не будет хорошо, когда он на самом деле теперь запрашивает неправильную вещь. Кроме того, используя toString() вместо name() чтобы получить имя свойства, вы можете переопределить toString() в вашем перечислении вернуть нечто иное, чем имя константы.

Недостатком использования перечислений является то, что система не может искать ничего, что не было известно во время компиляции, без какого-либо альтернативного способа доступа к Properties,

Там может быть библиотека, которая будет читать файл свойств и генерировать его в исходный файл с геттерами. Затем вам придется скомпилировать этот исходный файл с вашим кодом. Это была бы довольно изящная библиотека. Но, если этого не существует, я не думаю, что есть другой способ сделать это.

Даже если он существует, я не понимаю, как он мог бы знать, что key1 это String а также key2 является Integer, Тебе все равно, вероятно, придется где-нибудь сыграть. Это, или поддерживать отдельный файл метаданных, и тогда вы вернетесь к дополнительному обслуживанию.

Проблема в том, что вы можете изменить ключи файла свойств в любое время, и компилятор не может знать, что вы это сделали.

Лучшее, что я могу вам дать - это библиотеки, предназначенные для чтения файлов конфигурации. Проверьте библиотеку конфигурации Apache.

Мы с коллегой сейчас сталкиваемся с очень похожей проблемой, и мы провели некоторое исследование, чтобы выяснить, можно ли решить эту проблему с помощью рефлексии. К сожалению, нам не удалось ее решить, но я постараюсь уточнить нашу проблему и стратегию. Возможно, кто-то умный может использовать нашу базовую линию, чтобы построить что-то, что преодолеет ограничения, которые ставят нас назад

Постановка задачи: мы хотим прочитать значения в файле свойств и назначить эти значения полям в Java-объекте (объект настроек). Имена ключей для нас не имеют значения, и поэтому было бы оптимальным просто использовать имена полей Java в качестве имен ключей.

Это принесло бы два больших преимущества:

  1. Во-первых, это позволило бы нам удалить много избыточных строковых констант.
  2. Во-вторых, это позволило бы нам определить назначение поля в одном месте, поскольку наши классы настроек реализованы с использованием наследования.

Мы планировали определить метод в суперклассе, который использовал бы отражение, чтобы получить все поля экземпляра. Начиная с этого момента, наша стратегия заключается в том, чтобы пройти через все поля и:

  1. получить название поля,
  2. используйте это имя для поиска свойства в файле свойств,
  3. получите тип поля и используйте этот тип, чтобы преобразовать строковое значение, считанное из файла свойств, и впоследствии назначить его текущему полю.

Используя этот подход, можно было бы добавить новое свойство, просто добавив новое поле экземпляра. Никакого дополнительного кода для чтения или написания нового свойства не потребуется.

К сожалению, это невозможно из-за двух проблем:

  1. Компилятор Java может удалить информацию об именах полей, см. Этот ответ.
  2. В зависимости от JVM, используя Class#getDeclaredFields() может запретить доступ.
Другие вопросы по тегам