[spring-projects/spring-boot]允许从模块 jar 中贡献应用程序属性

2024-07-08 293 views
0

目前,application.propertiesapplication.yaml文件都是从类路径加载的,第一个匹配的获胜。这使得将通用属性捆绑到 jar 文件中变得很困难。如果我们能找到一种方法让 jar 也能贡献属性而无需实现 ,那就太好了EnvironmentPostProcessor

我们需要注意以下几点:

  • 我们应该按照什么顺序加载资源,以及如何确保开发人员可以覆盖贡献的值
  • 我们不想增加启动时间(例如进行完整的类路径搜索)
  • 我们不能破坏向后兼容性
  • 我们需要注意spring.config.import=classpath:

回答

4

排序会比较棘手。如果两个 jar 恰好提供application.properties具有相同值的文件,我们需要一种方法来确定哪一个会获胜。

8

order在 application.properties 中使用属性是一种简单的方法吗?

5

当我们修复这个问题时,我们应该研究#25033 背后的用例。

2

@philwebb & @wilkinsona,感谢你们的出色工作!

--spring.config.intergration-location=classpath*:/sink//[application.yml]在我的拉取请求 #25082 中,类似 #25080

依赖 jar 的配置只是为了减少使用它的项目的重复或错误工作。所以规则:最低顺序并且可以被任何人覆盖,不关心冲突(使用映射值),不覆盖更高/外部值,限制 2 个通配符,以 ' /' 或文件名结尾并通过 '/fold/' 过滤。该规则永远不会破坏向后兼容性。并使用新的参数来确保永远不会破坏向后兼容性。在我的实际项目(240 个 jar)中使用我提取的更新,启动时间并不慢,只是正常。我更喜欢在 xml(`<resource import="classpth :">`)中使用 spring,但是越来越多的云框架只提供 spring-boot' 风格的配置,真的没有使用 spring-boot 的后路

2

我更喜欢在 xml 中使用 spring() = 我更喜欢在 xml 中使用 spring(< resource import="classpath:*">)

1

我正在考虑一些类似于#25084 的事情,比如制作spring.config.name多值(或附加属性)并让库为其贡献自己的价值。

也许在某种程度上一切都变得荒谬,排序/优先级仍然很困难,但在大多数情况下,你不会期望发生碰撞/冲突,因为库拥有自己的垂直部分。

也许到最后你所需要的并不比EnvironmentPostProcessor为库开发人员添加一个更容易,但最终会更强大,并为我们各种堆栈中的一些粗糙边缘提供更简洁的解决方案,确保应用程序获得所有/仅他们需要的属性和各种秘密/设置都在一个位置。

1

基于spring-boot-cloud的项目特点如下:

  1. 分布式、松散且不确定的集成,
  2. 提供者与消费者互为客户端,存在多种通信和数据协议配置。
  3. 提供方和消费方是多对多的关系,导致暴露的配置不一样,决定了通过过滤名称的方式来获取配置是不可取的,而且存在向后兼容的问题,并且学习起来比较困难。
  4. 开发分布在不同的团队中,其中一个团队只专门负责自己的配置,提供他们所需的接口和配置。
  5. 数据的传输和消费都是基于接口的。
  6. 因此随着迭代开发次数的增加,从依赖方直接复制配置变得越来越困难,这种工作疏忽,懈怠,测试工作量巨大。

很多分布式开发团队都纠结于自己不熟悉的配置,其实他们根本不需要关心这些配置,只需要默认值和完全的控制权。

这个问题我想了很久,是架构和基础的问题,有的面试的时候,他们团队需要很多人去开发,维护,同步配置,其实是不需要的。

我看了spring boot源码,做了大量的实验,最后找到了我认为最好的解决方案,我的改动#25082,#25080影响点最小。完全符合你的顾虑。

3

我的主要用例是将配置属性拆分为多个文件以避免出现巨大的application.properties文件。这些多个属性文件不一定来自模块 jar,但这当然是可能的。实际上,可以使用不同的属性文件以逻辑方式对配置属性进行分组。

在 Sprig Boot 2.3 中,我通过如下方法解决了这个问题:

@PropertySource(
        ignoreResourceNotFound = true,
        value = { "classpath:config/authentication.properties",
                "classpath:config/authentication-${spring.profiles.active}.properties",
                "classpath:config/persistence.properties",
                "classpath:config/persistence-${spring.profiles.active}.properties" })

也就是说,由于PropertySources 不了解配置文件(请参阅#12822,该提案已被拒绝),我不得不模仿该机制,将其设置ignoreResourceNotFoundtrue

spring.config.import现在使用 Spring Boot 2.4,我可能可以直接用(我还没有尝试过)做类似的事情,但是我必须再次“模仿”Spring Boot 保留的配置文件特定行为application.properties,以及application.properties捆绑 JAR 之外的文件优先于 JAR 内部文件的其他机制。

那么像这样的事情怎么样:

spring.config.units=authentication,persistence

它的作用如下:

  • authentication[-*].properties使用与搜索相同的算法进行搜索application.properties(包括对 JAR 之外的配置文件和路径的支持)
  • persistence[-*].properties使用与搜索相同的算法进行搜索application.properties(包括对 JAR 之外的配置文件和路径的支持)
  • 关于顺序,使application.properties[-*].properties导入的单元获胜(这应该涵盖“从模块 JAR 导入默认属性”的情况)
  • 在导入的单元中,保留其声明的顺序(即:使authentication[-*].properties获胜persistence[-*].properties

仅我的观点。

5

如何向 中添加一个@ConfigurationProperties名为 的属性,该属性将采用与中的属性defaults类似的属性列表?默认属性不需要添加前缀,因为已经这样做了。这样,库就不需要创建额外的属性文件了。properties@SpringBootTest@ConfigurationProperties

4

我们已经支持通过初始化字段值或使用 来配置属性的默认值@DefaultValue。在这两种情况下,这些默认值都将反映在配置属性元数据中,并在 IDE 的自动完成期间显示。

在 1.x 中我们有一个location属性@ConfigurationProperties,允许指定外部文件的位置。经验表明,它工作得不是特别好,并且造成了相当多的混乱(例如https://github.com/spring-projects/spring-boot/issues/5111https://github.com/spring-projects/spring-boot/issues/5135),因此它被弃用然后被删除。允许直接设置属性的属性会重新引入我们不想发生的相同问题。它也不像将整个属性或 yaml 文件轻松添加到环境中那样广泛有用。

1

通过初始化字段的值或使用@DefaultValue

我不知道这个@DefaultValue注释,它似乎是在 2.2.0 中引入的。它或内联初始化是否允许使用 SPEL 的占位符?

0

不,不是。会执行类型转换 - 例如,您可以在属性上设置默认值 10s Duration- 但没有占位符解析或 SpEL 表达式求值。

如果你还有其他问题,请关注 Stack Overflow 或Gitter 。正如贡献指南中所述,我们更喜欢仅将 GitHub 问题用于错误和增强功能。

6

请参阅#27000 了解另一个想要贡献配置的示例。

9

是否可以允许合并默认属性而不是替换它们?

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplication.html#setDefaultProperties-java.util.Map-

添加一种新方法来允许添加而不是替换?

此后,诸如在 jar 中定义一些已知属性文件之类的操作有助于配置默认值。

目前我正在做类似的事情:

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
                                       SpringApplication application) {
        try {
            environment.getPropertySources().addLast(
                new ResourcePropertySource("management-defaults",
                    "/somepath/management.properties"));
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}
3

我能以某种方式削弱@wilkinsona 个人资料的优先级吗?

我想包含我的 application-customprofile.yml 的属性,但前提是它们未在我的 application.yml 中定义

编辑:这似乎有效

应用

library:
   customize:
      url:
         firstUrl: "https://app-overriding-url.com"

图书馆:

library:
   url:
      firstUrl: '${library.customize.url.firstUrl:https://librarys-own-url.com}'

或图书馆花式:

library:
   defaults:
      url:
         firstUrl: "https://librarys-own-url.com"
   url:
      firstUrl: '${library.customize.url.firstUrl:${library.defaults.url.firstUrl}}

可能会对某人有帮助吗?