Постановка проблемы
Я хочу загрузить свойства из файла свойств в classpath или во внешнем расположении до инициализации bean-компонентов. Потому что эти свойства также будут частью инициализации Бина. Я не могу автоматически связать эти свойства со стандартным application.properties Spring или его настройкой, потому что один и тот же файл свойств должен быть доступен нескольким depoyables.
Что я пробовал
I 'm осведомлен о событиях весенних приложений ;На самом деле, я уже подключаю ContextRefreshedEvent для выполнения некоторых задач после инициализации контекста Spring (компоненты Bean также инициализируются на этом этапе).
Для моего постановки задачи из описания SpringДокументы ApplicationEnvironmentPreparedEvent
выглядели многообещающе, но я не могу заставить их работать.
@SpringBootApplication
public class App {
public static void main(String[] args) throws IOException {
SpringApplication.run(App.class, args);
}
@EventListener
public void onStartUp(ContextRefreshedEvent event) {
System.out.println("ContextRefreshedEvent"); // WORKS
}
@EventListener
public void onShutDown(ContextClosedEvent event) {
System.out.println("ContextClosedEvent"); // WORKS
}
@EventListener
public void onEvent6(ApplicationStartedEvent event) {
System.out.println("ApplicationStartedEvent"); // WORKS BUT AFTER ContextRefreshedEvent
}
@EventListener
public void onEvent3(ApplicationReadyEvent event) {
System.out.println("ApplicationReadyEvent"); // WORKS WORKS BUT AFTER ContextRefreshedEvent
}
public void onEvent1(ApplicationEnvironmentPreparedEvent event) {
System.out.println("ApplicationEnvironmentPreparedEvent"); // DOESN'T WORK
}
@EventListener
public void onEvent2(ApplicationContextInitializedEvent event) {
System.out.println("ApplicationContextInitializedEvent"); // DOESN'T WORK
}
@EventListener
public void onEvent4(ApplicationContextInitializedEvent event) {
System.out.println("ApplicationContextInitializedEvent");
}
@EventListener
public void onEvent5(ContextStartedEvent event) {
System.out.println("ContextStartedEvent");
}
}
Обновление
Как подсказано M.Deinum в комментариях, япопытался добавить инициализатор контекста приложения, как показано ниже. Похоже, он тоже не работает.
public static void main(String[] args) {
new SpringApplicationBuilder()
.sources(App.class)
.initializers(applicationContext -> {
System.out.println("INSIDE CUSTOM APPLICATION INITIALIZER");
})
.run(args);
}
Обновление # 2
Хотя мое постановление проблемы касается загрузки свойств, мой вопрос / любопытство действительно о как запуститьнекоторый код перед тем, как классы инициализируются как бины и помещаются в контейнер Spring IoC . Теперь этим компонентам требуются значения некоторых свойств во время инициализации, и я не могу / не хочу автоматически связывать их по следующей причине.
Хотя, как указано в комментариях и ответах, то же самое можно сделать с помощьюВнешняя конфигурация и профили Spring Boot. Однако мне нужно поддерживать свойства приложения и свойства, связанные с доменом, отдельно. Ожидается, что свойства базового домена будут иметь не менее 100 свойств, которые будут расти со временем. У каждого из них есть файл свойств, каждый для своей среды (dev, SIT, UAT, Production), который будет переопределять одно или несколько базовых свойств. Это 8 файлов свойств. Теперь одно и то же приложение необходимо развернуть в нескольких регионах. Это делает его 8 * n
файлами свойств, где n
- количество географических регионов. Я хочу, чтобы все они хранились в общем модуле, чтобы к нему могли обращаться различные развертываемые объекты. Окружение и география будут известны во время выполнения как системные свойства.
Хотя это может быть достигнуто с помощью профилей Spring и порядка приоритетов, я хочу иметь программный контроль над ним ( Я бы также поддержалмой собственный репозиторий ). Например. Я написал бы удобную утилиту под названием MyPropUtil
и получил бы к ним доступ, например:
public class MyPropUtil {
private static Map<String, Properties> repository;
public static initialize(..) {
....
}
public static String getDomainProperty(String key) {
return repository.get("domain").getProperty(key);
}
public static String getAppProperty(String key) {
return repository.get("app").getProperty(key);
}
public static String getAndAddBasePathToAppPropertyValue(String key) {
...
}
}
@Configuration
public class MyComponent {
@Bean
public SomeClass getSomeClassBean() {
SomeClass obj = new SomeClass();
obj.someProp1(MyPropUtil.getDomainProperty('domainkey1'));
obj.someProp2(MyPropUtil.getAppProperty('appkey1'));
// For some properties
obj.someProp2(MyPropUtil.getAndAddBasePathToAppPropertyValue('some.relative.path.value'));
....
return obj;
}
}
Из документов кажется, что ApplicationEvents
и ApplicationInitializers
соответствуют моим потребностям, но я не могузаставить их работать для моей постановки проблемы.