• springboot 从环境变量读取配置的流程


    一、定义NACOS的地址环境变量配置。

    SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR=127.0.0.2:8848

    bootStrap的配置

     最终发现,环境变量会覆盖配置文件 的配置。

    1. @ConfigurationProperties(NacosConfigProperties.PREFIX)
    2. public class NacosConfigProperties {
    3. /**
    4. * Prefix of {@link NacosConfigProperties}.
    5. */
    6. public static final String PREFIX = "spring.cloud.nacos.config";
    7. /**
    8. * COMMAS , .
    9. */
    10. public static final String COMMAS = ",";
    11. /**
    12. * SEPARATOR , .
    13. */
    14. public static final String SEPARATOR = "[,]";
    15. private static final Pattern PATTERN = Pattern.compile("-(\\w)");
    16. private static final Logger log = LoggerFactory
    17. .getLogger(NacosConfigProperties.class);
    18. @Autowired
    19. @JsonIgnore
    20. private Environment environment;
    21. @PostConstruct
    22. public void init() {
    23. this.overrideFromEnv();
    24. }
    25. private void overrideFromEnv() {
    26. if (StringUtils.isEmpty(this.getServerAddr())) {
    27. String serverAddr = environment
    28. .resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}");
    29. if (StringUtils.isEmpty(serverAddr)) {
    30. serverAddr = environment.resolvePlaceholders(
    31. "${spring.cloud.nacos.server-addr:localhost:8848}");
    32. }
    33. this.setServerAddr(serverAddr);
    34. }
    35. if (StringUtils.isEmpty(this.getUsername())) {
    36. this.setUsername(
    37. environment.resolvePlaceholders("${spring.cloud.nacos.username:}"));
    38. }
    39. if (StringUtils.isEmpty(this.getPassword())) {
    40. this.setPassword(
    41. environment.resolvePlaceholders("${spring.cloud.nacos.password:}"));
    42. }
    43. }
    44. /**
    45. * nacos config server address.
    46. */
    47. private String serverAddr;
    48. /**
    49. * the nacos authentication username.
    50. */
    51. private String username;
    52. /**
    53. * the nacos authentication password.
    54. */
    55. private String password;
    56. /**
    57. * encode for nacos config content.
    58. */
    59. private String encode;
    60. /**
    61. * nacos config group, group is config data meta info.
    62. */
    63. private String group = "DEFAULT_GROUP";
    64. /**
    65. * nacos config dataId prefix.
    66. */
    67. private String prefix;
    68. /**
    69. * the suffix of nacos config dataId, also the file extension of config content.
    70. */
    71. private String fileExtension = "properties";
    72. /**
    73. * timeout for get config from nacos.
    74. */
    75. private int timeout = 3000;
    76. /**
    77. * nacos maximum number of tolerable server reconnection errors.
    78. */
    79. private String maxRetry;
    80. /**
    81. * nacos get config long poll timeout.
    82. */
    83. private String configLongPollTimeout;
    84. /**
    85. * nacos get config failure retry time.
    86. */
    87. private String configRetryTime;
    88. /**
    89. * If you want to pull it yourself when the program starts to get the configuration
    90. * for the first time, and the registered Listener is used for future configuration
    91. * updates, you can keep the original code unchanged, just add the system parameter:
    92. * enableRemoteSyncConfig = "true" ( But there is network overhead); therefore we
    93. * recommend that you use {@link ConfigService#getConfigAndSignListener} directly.
    94. */
    95. private boolean enableRemoteSyncConfig = false;
    96. /**
    97. * endpoint for Nacos, the domain name of a service, through which the server address
    98. * can be dynamically obtained.
    99. */
    100. private String endpoint;
    101. /**
    102. * namespace, separation configuration of different environments.
    103. */
    104. private String namespace;
    105. /**
    106. * access key for namespace.
    107. */
    108. private String accessKey;
    109. /**
    110. * secret key for namespace.
    111. */
    112. private String secretKey;
    113. /**
    114. * context path for nacos config server.
    115. */
    116. private String contextPath;
    117. /**
    118. * nacos config cluster name.
    119. */
    120. private String clusterName;
    121. /**
    122. * nacos config dataId name.
    123. */
    124. private String name;
    125. /**
    126. * a set of shared configurations .e.g:
    127. * spring.cloud.nacos.config.shared-configs[0]=xxx .
    128. */
    129. private List sharedConfigs;
    130. /**
    131. * a set of extensional configurations .e.g:
    132. * spring.cloud.nacos.config.extension-configs[0]=xxx .
    133. */
    134. private List extensionConfigs;
    135. /**
    136. * the master switch for refresh configuration, it default opened(true).
    137. */
    138. private boolean refreshEnabled = true;
    139. // todo sts support
    140. }
    141. }

    二、调试流程

     1.最终会从org.springframework.boot.context.properties.bind.Binder,是这个类的findProperty方法,会将一个配置类BEAN的每个属性都会循环寻找环境变量,配置文件等,是否能找到合适的属性定义,然后进行属性注入。
    1. private Object bindObject(ConfigurationPropertyName name, Bindable target, BindHandler handler,
    2. Context context, boolean allowRecursiveBinding) {
    3. ConfigurationProperty property = findProperty(name, context);
    4. if (property == null && context.depth != 0 && containsNoDescendantOf(context.getSources(), name)) {
    5. return null;
    6. }
    7. AggregateBinder aggregateBinder = getAggregateBinder(target, context);
    8. if (aggregateBinder != null) {
    9. return bindAggregate(name, target, handler, context, aggregateBinder);
    10. }
    11. if (property != null) {
    12. try {
    13. return bindProperty(target, context, property);
    14. }
    15. catch (ConverterNotFoundException ex) {
    16. // We might still be able to bind it using the recursive binders
    17. Object instance = bindDataObject(name, target, handler, context, allowRecursiveBinding);
    18. if (instance != null) {
    19. return instance;
    20. }
    21. throw ex;
    22. }
    23. }
    24. return bindDataObject(name, target, handler, context, allowRecursiveBinding);
    25. }

    从下面可以看到,环境变量的配置覆盖了bootStrap的配置。

    2.具体读取属性配置的实现类org.springframework.boot.context.properties.source.

    SpringIterableConfigurationPropertySource

    这里将.换成_ ,最终将读取

    SystemEnvironmentPropertySource.SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR
    

    3. 

    4.最终读取到这个值,并绑定到配置对象的属性中。

     5.由于环境变量的优先级高于配置文件,所以会优先读取环境变量的配置,然后读取完就返回了,不会再去配置文件属性列表中寻找。

     

  • 相关阅读:
    栅栏涂色题
    B. Inflation-Educational Codeforces Round 103 (Rated for Div. 2)
    P1529 [USACO2.4] 回家 Bessie Come Home 题解
    stm32(GD32,apm32),开优化后需要特别注意的地方
    Java简介
    C语言链表
    【Dive into Deep Learning / 动手学深度学习】第十章 - 第三节:注意力评分函数
    【STM32】硬件资源及芯片介绍
    数据结构栈的使用——马踏棋盘
    电力巡检系统无人机模块
  • 原文地址:https://blog.csdn.net/lipengyao2010/article/details/126136823