[spring-projects/spring-boot]如果另一个属性源包含绑定到同一目标的属性,则不遵循 _ 使用准则的环境变量仍会成功绑定

2024-04-23 526 views
2

我们有自定义属性,构建如下:

@ConfigurationProperties("yona")
@Configuration
public class YonaProperties
{
    @NestedConfigurationProperty
    private final AnalysisServiceProperties analysisService = new AnalysisServiceProperties();

AnalysisServiceProperties属性可以这样设置:

yona.analysisService.someProperty=someValue

或者通过环境变量,如下所示:

YONA_ANALYSIS_SERVICE_SOME_PROPERTY=someValue

在 Spring Boot 1.5 中,可以没有任何yona.analysisService.xxx属性,application.properties但仍然可以通过环境变量(如YONA_ANALYSIS_SERVICE_XXX.

在 Spring Boot 2.0.4 中,这种情况不再适用。中必须至少yona.analysisService.xxx存在一个application.properties。在环境xxx中设置application.properties并通过环境设置是可以的yyy,但至少需要有一个。

回答

9

这是一个重现上述行为的最小示例:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
@EnableConfigurationProperties(YonaProperties.class)
public class Gh14479Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Gh14479Application.class, args);
        YonaProperties yonaProperties = context.getBean(YonaProperties.class);
        System.out.println((yonaProperties.getAnalysisService().getAlpha()));
        System.out.println((yonaProperties.getAnalysisService().getBravo()));
    }

}

@ConfigurationProperties("yona")
class YonaProperties {

    private final AnalysisServiceProperties analysisService = new AnalysisServiceProperties();

    public AnalysisServiceProperties getAnalysisService() {
        return analysisService;
    }

    public class AnalysisServiceProperties {

        private String alpha;

        private String bravo;

        public String getAlpha() {
            return alpha;
        }

        public void setAlpha(String alpha) {
            this.alpha = alpha;
        }

        public String getBravo() {
            return bravo;
        }

        public void setBravo(String bravo) {
            this.bravo = bravo;
        }

    }

}

不带属性运行:

$ java -jar target/gh-14479-0.0.1-SNAPSHOT.jar
…
null
null

使用环境变量和命令行属性运行并且两者都生效:

$ YONA_ANALYSIS_SERVICE_ALPHA=one java -jar target/gh-14479-0.0.1-SNAPSHOT.jar --yona.analysis-service.bravo=two
…
one
two

仅使用命令行属性运行即可生效:

$ java -jar target/gh-14479-0.0.1-SNAPSHOT.jar --yona.analysis-service.bravo=two
…
null
two

仅使用环境变量运行,没有任何效果:

$ YONA_ANALYSIS_SERVICE_ALPHA=one java -jar target/gh-14479-0.0.1-SNAPSHOT.jar
…
null
null
8

确实是这样。感谢您制作复制品!

7

当仅设置环境变量时,yona.analysis-service将使用yona.analysis.service.alpha和调用配置属性名称yonaanalysisservicealpha以查看它是否是祖先。在这两种情况下false都会返回,因此看起来没有要绑定到实例的属性,AnalysisServiceProperties因此绑定停止。

yona.analysis-service.bravo除了环境变量之外,当在命令行上设置了属性时,配置属性名称yona.analysis-service也会用 来调用yona.analysis-service.bravo。它正确地确定它是传入名称的祖先,因此绑定继续,然后绑定两个属性。

5

上述行为是环境变量不满足记录要求的症状。具体来说,_不应在属性名称中使用。这意味着环境变量应该命名YONA_ANALYSISSERVICE_ALPHA而不是YONA_ANALYSIS_SERVICE_ALPHA.如果使用前者,绑定将按预期工作。

我暂时将其保留,因为当前的行为(至少对我来说)有点令人困惑。理想情况下,不符合所需准则的环境变量永远不应绑定,无论已配置的任何其他属性如何。

7

抱歉,我不确定您认为情况并非如此。属性类和配置application.properties都很好。这是环境变量的问题。回到原来的示例,您需要使用YONA_ANALYSISSERVICE_SOMEPROPERTY而不是YONA_ANALYSIS_SERVICE_SOME_PROPERTY分隔_符仅在属性之间使用,而不是在属性名称内使用。

1

嗯。这是否是 2.0 中宽松绑定稍微不那么宽松的一个方面? :)

7

是的,这是宽松绑定的一部分,但并不那么宽松。

2

好的,清楚了。有点不幸的是,它有时会起作用,具体取决于该属性是否以其他方式绑定。

9

我们希望通过忽略格式错误的环境变量的绑定来修复此问题。

1

按照我们的意愿修复此问题将会回归https://github.com/spring-projects/spring-boot/issues/10873

我认为我们有几个选择:

  1. 恢复 #10873 的更改,这样foo.the-bar只会产生FOO_THEBAR
  2. 以某种方式更改祖先检查,以便yona.analysis-service将其识别为祖先YONA_ANALYSIS_SERVICE_SOME_PROPERTY
  3. 接受当前的行为

2 感觉是最不糟糕的选择,但我不确定它有多现实。

9

我认为我们应该恢复 #10873 的更改,因为令人困惑的是 1.5 样式属性仅有时有效。

1

我们也许可以在 2.1 中恢复#10873,但我认为在 2.0.x 中这样做有点苛刻。如果我没记错的话,#10873 也是应 Spring Cloud 项目的请求添加的(但我不记得是哪一个了)。

3

我想知道我们是否可以让祖先检查更宽松一些?忽略不是字母的所有内容,然后忽略大小写,看看一个是否以另一个开头怎么样?偶尔的误报并不是世界末日,因为它只是用作短路绑定的一种方式,不是吗?

3

祖先检查也用于MapBinder绑定映射中的条目时。使检查宽松可能会导致一些转换异常,但我不完全确定。

0

我尝试添加一个单独的、更宽松的祖先检查,并且仅从containsDescendantOf各种ConfigurationPropertySource实现上的各种方法中调用它。为了模拟最坏的情况,我只是返回true。如果没有启用自动配置,它会修复上述情况。启用自动配置后,它会破坏其他属性绑定。具体来说,我看到了这个失败:

org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.info.build.location.u-r-l' to java.net.URL
    at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:250) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:226) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$5(Binder.java:333) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:73) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$7(Binder.java:341) ~[classes/:na]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_181]
    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_181]
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_181]
    at org.springframework.boot.context.properties.bind.Binder.lambda$6(Binder.java:342) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:441) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withBean(Binder.java:427) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.access$5(Binder.java:424) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindBean(Binder.java:339) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:278) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:221) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$5(Binder.java:333) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:73) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$7(Binder.java:341) ~[classes/:na]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_181]
    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_181]
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_181]
    at org.springframework.boot.context.properties.bind.Binder.lambda$6(Binder.java:342) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:441) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withBean(Binder.java:427) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.access$5(Binder.java:424) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindBean(Binder.java:339) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:278) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:221) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$5(Binder.java:333) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:73) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$7(Binder.java:341) ~[classes/:na]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_181]
    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_181]
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_181]
    at org.springframework.boot.context.properties.bind.Binder.lambda$6(Binder.java:342) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:441) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withBean(Binder.java:427) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.access$5(Binder.java:424) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindBean(Binder.java:339) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:278) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:221) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:210) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:192) ~[classes/:na]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:82) ~[classes/:na]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:107) ~[classes/:na]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:93) ~[classes/:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1691) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:818) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:724) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:197) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1267) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1124) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [classes/:na]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) [classes/:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [classes/:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242) [classes/:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230) [classes/:na]
    at com.example.demo.Gh14479Application.main(Gh14479Application.java:15) [classes/:na]
Caused by: java.lang.IllegalStateException: Unable to get value for property u-r-l
    at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.lambda$0(JavaBeanBinder.java:307) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder$Bean.get(JavaBeanBinder.java:186) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:49) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.lambda$7(Binder.java:341) ~[classes/:na]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_181]
    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_181]
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_181]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_181]
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_181]
    at org.springframework.boot.context.properties.bind.Binder.lambda$6(Binder.java:342) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:441) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.withBean(Binder.java:427) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder$Context.access$5(Binder.java:424) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindBean(Binder.java:339) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:278) ~[classes/:na]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:221) ~[classes/:na]
    ... 99 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.lambda$0(JavaBeanBinder.java:304) ~[classes/:na]
    ... 118 common frames omitted
Caused by: java.io.FileNotFoundException: class path resource [META-INF/build-info.properties] cannot be resolved to URL because it does not exist
    at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:195) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    ... 123 common frames omitted

这是由于对 所持有的 的getURL调用而发生的。Resourceorg.springframework.boot.autoconfigure.info.ProjectInfoProperties.Build