Spring Boot 2 - 在豆子初始化之前做一些事情
问题陈述
我想在初始化 Bean 之前从类路径中的属性文件或外部位置加载属性。这些属性也是 Bean 初始化的一部分。我无法自动连接Spring标准apprament.properties或其自定义的属性,因为相同的属性文件必须可由多个可部署对象访问。
我尝试了什么
我知道春季应用事件;事实上,我已经挂接了 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 个属性,并且该属性会随着时间的推移而增长。应用程序属性和与域相关的属性都有一个用于不同环境(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