Какова наилучшая стратегия для загрузки свойств?

У меня есть несколько классов, которым необходимо загрузить некоторые файлы свойств, и мне было интересно, какие лучшие методы для этого. Я подумал о двух основных подходах:

  • Жестко задайте имя файла свойств в каждом классе, а затем используйте класс Properties для загрузки из FileInputStream, что может быть проблематичным, если кто-то решит изменить имя файла свойств, так как это жестко закодированные в коде.

    public class A {
        public A() {
            Properties p = new Properties().load(
                    new FileInputStream("properties/Aconfig.properties"));
            String value = p.getProperty("key", "");
        }        
    }
    
  • Создайте метод, который, учитывая имя класса, загружает файл свойств с тем же именем, что и класс. Хотя этот подход не требует жесткого кодирования имени файла свойств, он требует, чтобы мы соблюдали какое-либо соглашение при именовании файлов, что может вызвать путаницу.

    public class A {
        public A() {
            Properties p = PropertiesHelper.loadFromClassName(A.class.getName());
            // here, we **assume** that there is a A.properties file in the classpath.
        }
    }
    

Тем не менее, может быть много других более элегантных подходов, и поэтому я задавал следующие вопросы: i) Каковы наилучшие методы для загрузки файлов свойств в Java?; ii) Используете ли вы какой-либо вспомогательный класс, который заботится о работе?; iii) Где (в коде) вы обычно загружаете файл свойств?

Кроме того, нормально ли для класса "автоматически загружать" его свойства? Или мне нужно передать аргументы, которые мне нужны для конструктора? Проблема передачи аргументов заключается в том, что для некоторых классов существует слишком много (~ 20, которые представляют параметры в статистической модели).

Ответ 1

Практика лучше всего заключается в использовании какого-то контейнера зависимостей - например Spring Framework или Google Guice.

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

Это также помогает со многими и многими другими вещами в дополнение к загрузке свойств:-) - попробуйте, и вы будете удивляться, как вы когда-либо жили.

Обновление: Кстати, ваш другой вопрос также является одной из тех вещей, о которых Spring позаботится.

Обновление # 2: Я просто понял, что уже пытался нажать Spring на вас:-) Рискуя повторяя, Spring действительно поможет с абстракцией здесь. В зависимости от того, что вы храните в файлах свойств, вам могут вообще не понадобиться (если они имеют дело с конфигурацией), или вы получите очень хороший API для работы с ними (если это ресурсные пакеты или что-то подобное).

Ответ 2

Имейте несколько мест для файлов свойств и загружайте их (один за другим) в один объект Properties. Эта схема позволяет отображать значение по умолчанию, которое затем может быть переопределено в нескольких точках.

Ответ 3

Имена файлов можно легко передать в командной строке для приложения. Это можно сделать либо как arg для основного метода (после имени основного класса) или как свойство (поскольку aperkins ссылается, я верьте), используя - флаг D.

Ответ 4

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

Хорошая вещь об этом - это стандарт, но они могут переопределить его местоположение/имя с помощью аргумента командной строки.

Только мои 2 цента.

Ответ 5

Я бы предложил избегать использования путей, связанных с файлами и файловой системой. Обычно лучше использовать пути к классам (hmm, no pun предназначенные...), потому что:  - он делает ваш код поддающимся проверке путем разделения загрузчиков классов между временем выполнения и временем тестирования, что обычно выполняется любой достойной системой сборки  - он делает ваше местоположение кода независимым и позволяет игнорировать проблемы ОС  - он заставляет ваш код работать так же, как автономное приложение или внутри контейнера (легкий, сервлет, сервер приложений, что угодно...)

Вы можете взглянуть на PropertyResourceBundle, у которого есть хорошая дополнительная функция, которая известна в Locale, поэтому вы можете определить разные свойства с различными настройками Locale. Обратите внимание, что Locale можно злоупотреблять, чтобы обеспечить параметризацию независимо от проблем l10n или i18n, например. Я использовал в проекте "windows" и "linux" locale, потому что вы можете создать свой собственный экземпляр Locale и передать его загрузчику.

Или вы можете просто построить путь самостоятельно...

Или вы можете загрузить свои свойства из входного потока:

      Properties prop = Properties.load(getClass().getResourceAsStream("/myprops"));

НТН.