Spring 引导命令行 属性 未覆盖 application.properties 中定义的 属性

Spring Boot command line property not overriding property defined in application.properties

我创建了一个 Spring 启动应用程序,它使用了旧版库。这个遗留库在 XML 中定义了许多 Spring 个 Bean。其中之一将 属性 值作为构造函数参数:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="myBean" class="com.em.MyBean">
        <constructor-arg name="url" value="${my.url}"/>
    </bean>
</beans>

在我的 Spring 引导应用程序中,我有一个 application.properties 定义此 属性 如下:

my.url=http://localhost:8080

我在本地使用 Maven Spring 引导插件 运行 我的应用程序如下:

mvn spring-boot:run

并且 属性 值按预期注入到 bean 中。

如果我尝试像这样在命令行上覆盖 my.url 属性:

mvn spring-boot:run -Dmy.url=http://www.override.net

未使用覆盖值,而是使用 application.properties 中的值。

根据 Spring 引导文档,命令行中的值应作为第一优先级选取:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html。这里似乎不是这种情况,因为如果我从 application.properties 中删除 属性 ,那么将使用命令行中传入的值,因此不会完全忽略命令行值. application.properties 值似乎覆盖了命令行值。

有人知道发生了什么事吗?

使用 -D 设置系统 属性。 Spring 引导可以使用系统属性中的配置,所以一般来说,它会起作用。但是,如果 spring-boot:run 为您的应用程序派生一个单独的 JVM,它将无法工作,因为系统 属性 将设置在错误的 JVM 上。由于它不起作用,我想这就是正在发生的事情。

您可以使用 -Drun.arguments 将参数传递给正在 运行 的应用程序,无论它是否是 运行 在派生的 JVM 中。参数应该是一个以逗号分隔的列表,每个列表都以 -- 为前缀。例如,设置 my.url:

mvn spring-boot:run -Drun.arguments=--my.url=http://www.override.net

此问题的另一个可能原因是您的 main 方法没有将它接收到的参数传递到它创建的 SpringApplication 中。您还应该检查您的主要方法是否与此类似:

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

请注意,args 被传递到对 SpringApplication.run 的调用中。

我最终通过更改为 Spring 启动应用程序定义遗留库中的 bean 的方式解决了这个问题。我没有使用定义 bean 的遗留应用程序的 applicationContext.xml,而是将它们作为 @Bean 添加到我的配置 class 中。这解决了问题。

<context:property-placeholder location="classpath:application.properties"/>

从我的 beans.xml 文件中删除上面的行 (context:属性-placeholder) 解决了这个问题。我相信 classpath:application.properties 正在 确切地 锁定在哪里(防止覆盖)。

在我的例子中,我在 属性-placeholder 上定义了这个:

local-override="true"

所以我删除了它并解决了问题。

只是添加一个典型的错误:应用程序 main class 中使用的 SpringApplication.run 方法接受可变长度参数,如果您不提供任何参数,则不会抛出编译时警告:

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

args 参数从 main 方法传递到 SpringApplication.run 很重要。如果不这样做,则不会选取或生效任何命令行参数。