Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring是否遵循应用程序配置的命名约定?_Java_Spring_Spring Boot - Fatal编程技术网

Java Spring是否遵循应用程序配置的命名约定?

Java Spring是否遵循应用程序配置的命名约定?,java,spring,spring-boot,Java,Spring,Spring Boot,问题: 在application.properties中定义的配置不被环境变量覆盖 我在spring配置方面遇到了一个奇怪的问题,即在应用程序中定义的配置。当以特定方式命名配置时,环境变量不会覆盖属性。正如操作系统中提到的,环境变量优先于应用程序.属性,但当配置定义为myExternal\u url时不会发生这种情况,但当配置定义为my\u external\u url(在下面的示例代码中,我们需要在ApplicationProperties.java和application.propertie

问题: 在application.properties中定义的配置不被环境变量覆盖

我在spring配置方面遇到了一个奇怪的问题,即在
应用程序中定义的配置。当以特定方式命名配置时,环境变量不会覆盖属性。正如操作系统中提到的,环境变量优先于
应用程序.属性
,但当配置定义为
myExternal\u url
时不会发生这种情况,但当配置定义为
my\u external\u url
(在下面的示例代码中,我们需要在
ApplicationProperties.java
application.properties
中将配置更改为
my\u external\url

示例代码-

@SpringBootApplication
public class ConfigApplication implements ApplicationRunner {

  @Autowired private ApplicationProperties applicationProperties;

  public static void main(String[] args) {
    SpringApplication.run(ConfigApplication.class, args);
  }

  @Override
  public void run(ApplicationArguments arg0) {
    System.out.println("External URL = " + applicationProperties.getMyExternalUrl());
  }
}
应用程序Bean配置-

@Configuration
public class AppConfig {

  @Bean
  @ConfigurationProperties(prefix = "")
  public ApplicationProperties applicationProperties() {
    return new ApplicationProperties();
  }
}
应用程序属性
类-

public class ApplicationProperties {

  @Value("${myExternal_url}")
  private String myExternalUrl;

  public String getMyExternalUrl() {
    return this.myExternalUrl;
  }

  public void setMyExternalUrl(String myExternalUrl) {
    this.myExternalUrl = myExternalUrl;
  }
}
application.properties

myExternal_url=external_url_env_application_properties
这可能是什么原因

编辑-添加渐变 梯度配置

plugins {
    id 'org.springframework.boot' version '2.4.0-M1'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    compileOnly 'org.projectlombok:lombok:1.18.6'
    annotationProcessor 'org.projectlombok:lombok:1.18.6'
}

test {
    useJUnitPlatform()
}
编辑2

跟踪日志显示myExternal_url已从环境变量正确解析。然后Spring通过调用
AutowiredNotationBeanPostProcessor
尝试解析自动关联依赖项“
applicationProperties
”,然后值被application.properties值覆盖(屏幕截图)

  • 我无法在
    2.3.1.RELEASE
    中重现您的问题,它正在按预期工作,并被我的环境变量覆盖

  • 但是,我没有看到spring文档中说,
    @Value(${myExternal_url}”)
    也使用松弛绑定。我看到的只是
    @ConfigurationProperties
    将使用松弛绑定

  • 因此,我将按如下方式更新您的类(即使它在
    2.3.1.RELEASE
    中使用和不使用它)
    @Value
    注释已删除

  • 请注意,这两个属性仍将存在于
    环境中
    ,但当它绑定时,似乎会决定一个属性是否覆盖另一个属性。您可以通过打印看到这一点。这里我从
    应用程序上下文
    获取
    环境
    ,但您可以
    自动连线
    环境
    并进行测试
  • 为了确认上面的一点,即只有
    @ConfigurationProperties
    支持轻松绑定,但不支持
    @Value

Spring确实支持某种松散绑定形式的命名约定(正如@Kavithakaran kanapathipillai所指出的)。对于和@Value注释,Spring尝试按照使用中定义的顺序解析配置源中的变量

如回答@夢のの夢 - spring使用
@Value(${myExternal\u url}”)
与环境变量正确匹配属性,但后来被
@ConfigurationProperties(prefix=”“)
覆盖

由于bean
ApplicationProperties
被定义为
@ConfigurationProperties(prefix=”“)
,Spring尝试将变量与配置源匹配(使用宽松绑定),并在application.propertied变量
myexternalur
中找到匹配项,并覆盖使用
@Value(${myExternal u url})解析的属性
。问题在于同时使用
@Value
@ConfigurationProperties(prefix=”“)

旁注-
@Value
支持并且Spring建议使用kebab大小写定义@Value属性名

从文件-

如果确实要使用@Value,建议您参考属性 使用其规范形式的名称(烤肉串大小写仅使用小写) 这将允许Spring Boot使用与它相同的逻辑 当放松绑定@ConfigurationProperties时。例如, @值(“{demo.item-price}”)将拾取demo.item-price和 application.properties文件中的demo.itemPrice表单,以及 系统环境中的DEMO_ITEMPRICE。如果使用 @值(“{demo.itemPrice}”),改为demo.item-price和demo\u itemPrice 不会被考虑


TL;DR
@Value
从注入的系统变量中具有正确的
myExternal\u Url
,但其值稍后由
@ConfigurationProperties
设置

跟踪日志是正确的,因为Spring的排序将把
systemEnvironment
放在propertySource列表中
classpath:/application.properties
之前

您遇到的问题是由于同时使用
@Value
@ConfigurationProperties
来注入/绑定您的属性。 假设这些是您提供的值:

system:
  myExternal_Url: foo
  my_external_url: bar
applications.properties:
  myExternal_url: aaa
在应用程序属性中:

  @Value("${myExternal_url}")
  private String myExternalUrl; // injected with foo
myExternalUrl
正确地注入了值(
foo
)您在环境变量中定义了。但是,
@ConfigurationProperties
使用setter方法将后的值绑定到。由于它使用宽松的绑定,它会检查
myExternalUrl
的不同变体,它首先查找系统变量中的内容,并发现
myExternal\u url
(驼峰和下划线)不是一种宽松的绑定形式,但
my_external\u url
(仅下划线)是。因此
my_external\u url
的值提供给setter:

public void setMyExternalUrl(String myExternalUrl) { // bar
  this.myExternalUrl = myExternalUrl; // myExternalUrl is reassigned from foo to bar
}
因此,应该清楚的是,
@Value
将始终被覆盖,因为
@ConfigurationProperties
在之后绑定值。只需:

public class ApplicationProperties {
    private String myExternalUrl;
    ...

然后在您的系统中定义一个绑定表单-
MY_EXTERNAL\u URL
MY EXTERNAL URL
、或
MY_EXTERNAL\u URL
(可能还有更多)-然后在应用程序中使用一致的大小写。yml以防您不需要系统变量

my-external-url=aaa
旁注。建议您使用表单
MY\u EXTERNAL\u URL
作为系统环境
  @Value("${myExternal_url}")
  private String myExternalUrl; // injected with foo
public void setMyExternalUrl(String myExternalUrl) { // bar
  this.myExternalUrl = myExternalUrl; // myExternalUrl is reassigned from foo to bar
}
public class ApplicationProperties {
    private String myExternalUrl;
    ...

my-external-url=aaa