springcloud项目命令行参数不生效

301 阅读2分钟

由于要把项目部署到服务网格上,需要配置自定义监听端口,想在项目启动命令配置-Dserver.port=${PORT}启动程序。结果发现使用的还是bootstrap.yml远程配置中心配置的端口号。

默认情况下,Spring会按照以下顺序加载属性源:

  1. 命令行参数
  2. Java系统属性
  3. 操作系统环境变量
  4. 随项目打包的属性文件,例如application.propertiesapplication.yml
  5. @PropertySource注解指定的属性源

既然这样就得看看为啥先使用配置文件,没有使用命令行参数

经过一顿debug,spring使用的关键代码有


public class PropertySourceBootstrapConfiguration implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered

org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration#initialize //将PropertySourceLocator加载的配置源放入应用上下文配置环境
private void insertPropertySources(MutablePropertySources propertySources,
      List<PropertySource<?>> composite) {
   MutablePropertySources incoming = new MutablePropertySources();
   List<PropertySource<?>> reversedComposite = new ArrayList<>(composite);
   // Reverse the list so that when we call addFirst below we are maintaining the
   // same order of PropertySources
   // Wherever we call addLast we can use the order in the List since the first item
   // will end up before the rest
   Collections.reverse(reversedComposite);
   for (PropertySource<?> p : reversedComposite) {
      incoming.addFirst(p);
   }
   PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties();
   Binder.get(environment(incoming)).bind("spring.cloud.config",
         Bindable.ofInstance(remoteProperties));
   if (!remoteProperties.isAllowOverride() || (!remoteProperties.isOverrideNone()
         && remoteProperties.isOverrideSystemProperties())) {//重载系统参数,默认是将配置重载。所以会使用配置文件的,不使用命令行参数。放到配置源List的头部来实现
      for (PropertySource<?> p : reversedComposite) {
         propertySources.addFirst(p);
      }
      return;
   }
   if (remoteProperties.isOverrideNone()) {
      for (PropertySource<?> p : composite) {
         propertySources.addLast(p);
      }
      return;
   }
   if (propertySources.contains(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
      if (!remoteProperties.isOverrideSystemProperties()) {
         for (PropertySource<?> p : reversedComposite) {
            propertySources.addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, p);
         }
      }
      else {
         for (PropertySource<?> p : composite) {
            propertySources.addBefore(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, p);
         }
      }
   }
   else {
      for (PropertySource<?> p : composite) {
         propertySources.addLast(p);
      }
   }
}

在系统启动过程中PropertySourceBootstrapConfiguration加载了两次,猜测第一次是加载cloud配置,第二次是加载application配置,第二次加载的时候由于默认的配置是新的配置重载原有的命令行参数、环境变量等配置,所以命令行参数没有生效

解决方案

配置参数调整,就会先加载命令行的参数

spring.cloud.config.overrideSystemProperties=false

org.springframework.cloud.bootstrap.config.PropertySourceBootstrapProperties还有很多配置可以根据需求调整

@ConfigurationProperties("spring.cloud.config")
public class PropertySourceBootstrapProperties {

   /**
    * Flag to indicate that the external properties should override system properties.
    * Default true.
    */
   private boolean overrideSystemProperties = true;

   /**
    * Flag to indicate that {@link #isOverrideSystemProperties()
    * systemPropertiesOverride} can be used. Set to false to prevent users from changing
    * the default accidentally. Default true.
    */
   private boolean allowOverride = true;

   /**
    * Flag to indicate that when {@link #setAllowOverride(boolean) allowOverride} is
    * true, external properties should take lowest priority and should not override any
    * existing property sources (including local config files). Default false.
    */
   private boolean overrideNone = false;
}