问题陈述
我想在初始化bean之前从类路径或外部位置的属性文件中加载属性。这些属性也是Bean初始化的一部分。我无法通过Spring的标准 application.properties 或其自定义项自动装配属性,因为同一属性文件必须可由多个可部署对象访问。
我尝试过的
我知道Spring Application Events;实际上,我已经很着迷了 ContextRefreshedEvent 用于在Spring Context初始化之后执行一些任务(在此阶段还初始化Bean)。
对于我的问题陈述,从Spring Docs 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
虽然我的问题陈述是关于加载属性的,但我的问题/好奇心实际上是关于如何在将类初始化为bean并放入Spring IoC容器之前运行一些代码。现在,这些Bean在初始化期间需要一些属性值,由于以下原因,我不希望/不想对其进行自动装配:
如评论和答案中所述,可以使用Spring Boot的外部化配置和配置文件完成相同的操作。但是,我需要分别维护应用程序属性和与域相关的属性。基本域属性应至少具有100个属性,并且该数目随时间增长。应用程序属性和与域相关的属性都具有用于不同环境(开发,SIT,UAT,生产)的属性文件。属性文件会覆盖一个或多个基本属性。这是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
似乎很适合我的需求,但是我无法让它们用于我的问题陈述。