java - 在初始化时加载 Spring Boot 属性并尊重所有属性并根据属性文件中的值控制 @Aspect
问题描述
我们正在使用@PropertySources
. 现在我想@Aspect
基于属性启用/禁用。我尝试使用@ConditionalOnExpression
which 不起作用。我通过创建一个propertyplaceholderconfig
. 即使在相同的情况下,它也不起作用。然后我尝试@profile
了最初也没有工作。
我想出的是,这些变量在启动时propertysource
或propertyplaceholder
在启动时使用 bean 时并未初始化。某些变量总是被忽略,例如(logging.file)。但@Value
工作正常。为了设置这些变量,我必须将它们作为 JVM 参数传递。
所以我的问题是:
1. 如何让 spring 在启动时始终读取指定的属性文件并尊重所有这些文件?
2.这是启用/禁用的最佳方式@Aspect
。使用@profile
or@ConditionalOnExpression
还是别的什么?
目前,我们logging.file
在 main 方法中进行设置,因为它的行为方式也相同。但是你们知道这不是正确的方法,因为我最终可能会像这样一个一个地添加属性。我想将所有属性放入外部文件中,以便 spring 读取这些文件并设置其属性。
我们的物业结构:
- common.properties #这个有所有通用属性
- service.properties #特定于服务的属性。这还将包含来自 common.properties 的现有属性,这些属性将被覆盖。
我知道我可以使用个人资料。但是,我们希望将属性保留在外部,如果您要更改属性,则需要重新启动服务。我也不想将变量作为 JVM 参数传递,然后我必须以这种方式传递大部分变量。传递 -Dspring.config.location 也很困难,common.properties
因为service.properties
每个服务都使用了“service.properties”文件名。
示例代码:
主类:
@PropertySources({
@PropertySource(value = "file:${property_path}/common.properties", ignoreResourceNotFound = false),
@PropertySource(value = "file:${property_path}/service1.properties", ignoreResourceNotFound = true) })
public class MainClass {
static String logDirectory = ApplicationContext.getGlobalProperty("logging.file");
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MainClass.class);
Properties properties = new Properties();
properties.put("logging.file", logDirectory);
springApplication.setDefaultProperties(properties);
springApplication.run(args);
}
}
应用环境:
@Configuration
@EnableAutoConfiguration
public class ApplicationContext implements EnvironmentAware {
private static Environment environment;
@Override
public void setEnvironment(Environment environment) {
ApplicationContext.environment = environment;
}
public static String getGlobalProperty(String propertyName) {
return environment.getProperty(propertyName);
}
}
在这里,您可以看到我曾经environment
获得的任何方式property
。有没有办法使用环境设置属性,以便在 spring boot 初始化本身时填充属性?
我们还可以实现ApplicationContextInitializer
和覆盖initialize
读取属性的方法。但是如何让它读取 2 个属性文件并用最新值覆盖重复的属性?参考(我不确定如何以这种方式实现我的要求。)。即使在这种情况下,您听起来也不像是想用锤子杀死蚊子吗?
当前工作解决方案:
@Aspect
@Profile("!production")
@Configuration
public class ControllerAspect {
@pointcut(....)
} //Here also I've to pass spring.profiles.active as JVM params.
//setting the value in common.properties or service1.properties is not working.
我是弹簧靴的新手,所以请让我知道以获取更多说明。
解决方案
似乎 Spring 默认会在初始化时加载一些属性,除非您专门编写逻辑来覆盖它们(就像我在 中写的那样MainClass.java
),否则没有选项可以覆盖这些属性。其中一些包括(logging.file,@ConditionalonExpression 中使用的键)。
一些有自己挑战的技巧:
- 在类路径中指定属性
application.properties
。在早期阶段加载的变量总是从此文件中读取。挑战:我已将所有属性紧密耦合到 jar 中,为了更改值,我必须重新编译并重新启动 Jar。 - 使用配置文件并定义
application.properties
为application-profile.properties
. 挑战:我必须创建这么多配置文件,但之前的挑战仍然存在。 - 将属性值作为 JVM 参数传递为
-Dproperty.key=value
. 挑战:认真吗?我应该发送多少属性作为 JVM 参数? - 实现
ApplicationContextInitialize
和覆盖initialize
方法。挑战:不建议覆盖 Spring 的默认行为,并且仅将其用于读取属性文件是不是有点矫枉过正?
解决方案:
用于-Dspring.config.location
指定属性文件。在这种情况下,spring 总是只从指定的位置读取属性。您也可以提供多个属性文件。有关更多详细信息,请参阅此内容。如果您在目录弹簧以相反的顺序加载它们时给出属性位置,似乎。但是,如果您指定文件,它将遵循指定的顺序。
注意:所有这些都可以组合在一起。要了解优先级,请参阅此。
推荐阅读
- css - SVG 图标在 Internet Explorer 中不起作用
- c# - 如何使用 c# 在 NFC 标签(卡:NTag-213,阅读器:ACR122)中读取和写入数据
- python - 应用于熊猫数据框中的两列时出现 Difflib 错误
- firebase - 传递 Firestore 文档的 Id 时,角度路由参数更改为小写
- installation - pkill 似乎没有在 Ubuntu 18.04 LTS 中删除 dpkg 进程
- javascript - 循环遍历json对象并将其放入html表中
- android - Google Play 开发者页面已更改?
- javascript - 过滤对象数组
- dialogflow-es - 与 Dialogflow 集成的 Telegram Bot 中的随机消息顺序
- android - 如何使用 MediaMuxer 将音频合并到视频中