浏览代码

add a config adjust the property source overridden behavior (#4409)

feat: add a config adjust the property source overridden behavior
biubiupiu 2 年之前
父节点
当前提交
2cc9fc84bd

+ 1 - 1
CHANGES.md

@@ -5,6 +5,6 @@ Release Notes.
 Apollo 2.1.0
 
 ------------------
-
+* [Add a config adjust the property source overriden behavior](https://github.com/apolloconfig/apollo/pull/4409)
 ------------------
 All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/11?closed=1)

+ 10 - 2
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializer.java

@@ -39,6 +39,7 @@ import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.core.Ordered;
 import org.springframework.core.env.CompositePropertySource;
 import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.StandardEnvironment;
 
 /**
  * Initialize apollo system properties and inject the Apollo config in Spring Boot bootstrap phase
@@ -90,7 +91,8 @@ public class ApolloApplicationContextInitializer implements
       ApolloClientSystemConsts.APOLLO_META,
       ApolloClientSystemConsts.APOLLO_CONFIG_SERVICE,
       ApolloClientSystemConsts.APOLLO_PROPERTY_ORDER_ENABLE,
-      ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE};
+      ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE,
+      ApolloClientSystemConsts.APOLLO_OVERRIDE_SYSTEM_PROPERTIES};
 
   private final ConfigPropertySourceFactory configPropertySourceFactory = SpringInjector
       .getInstance(ConfigPropertySourceFactory.class);
@@ -140,7 +142,12 @@ public class ApolloApplicationContextInitializer implements
 
       composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));
     }
-
+    if (!configUtil.isOverrideSystemProperties()) {
+      if (environment.getPropertySources().contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
+        environment.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, composite);
+        return;
+      }
+    }
     environment.getPropertySources().addFirst(composite);
   }
 
@@ -215,4 +222,5 @@ public class ApolloApplicationContextInitializer implements
   public void setOrder(int order) {
     this.order = order;
   }
+
 }

+ 12 - 7
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java

@@ -20,6 +20,7 @@ import com.ctrip.framework.apollo.Config;
 import com.ctrip.framework.apollo.ConfigChangeListener;
 import com.ctrip.framework.apollo.ConfigService;
 import com.ctrip.framework.apollo.build.ApolloInjector;
+import com.ctrip.framework.apollo.core.ApolloClientSystemConsts;
 import com.ctrip.framework.apollo.spring.events.ApolloConfigChangeEvent;
 import com.ctrip.framework.apollo.spring.util.SpringInjector;
 import com.ctrip.framework.apollo.util.ConfigUtil;
@@ -40,11 +41,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
 import org.springframework.context.EnvironmentAware;
 import org.springframework.core.Ordered;
 import org.springframework.core.PriorityOrdered;
-import org.springframework.core.env.CompositePropertySource;
-import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.Environment;
-import org.springframework.core.env.MutablePropertySources;
-import org.springframework.core.env.PropertySource;
+import org.springframework.core.env.*;
 
 /**
  * Apollo Property Sources processor for Spring Annotation Based Application. <br /> <br />
@@ -110,12 +107,20 @@ public class PropertySourcesProcessor implements BeanFactoryPostProcessor, Envir
     if (environment.getPropertySources()
         .contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
 
-      // ensure ApolloBootstrapPropertySources is still the first
-      ensureBootstrapPropertyPrecedence(environment);
+      if (configUtil.isOverrideSystemProperties()) {
+        // ensure ApolloBootstrapPropertySources is still the first
+        ensureBootstrapPropertyPrecedence(environment);
+      }
 
       environment.getPropertySources()
           .addAfter(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME, composite);
     } else {
+      if (!configUtil.isOverrideSystemProperties()) {
+        if (environment.getPropertySources().contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
+          environment.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, composite);
+          return;
+        }
+      }
       environment.getPropertySources().addFirst(composite);
     }
   }

+ 12 - 0
apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java

@@ -58,6 +58,7 @@ public class ConfigUtil {
   private boolean propertiesOrdered = false;
   private boolean propertyNamesCacheEnabled = false;
   private boolean propertyFileCacheEnabled = true;
+  private boolean overrideSystemProperties = true;
 
   public ConfigUtil() {
     warnLogRateLimiter = RateLimiter.create(0.017); // 1 warning log output per minute
@@ -72,6 +73,7 @@ public class ConfigUtil {
     initPropertiesOrdered();
     initPropertyNamesCacheEnabled();
     initPropertyFileCacheEnabled();
+    initOverrideSystemProperties();
   }
 
   /**
@@ -416,6 +418,10 @@ public class ConfigUtil {
     return propertyFileCacheEnabled;
   }
 
+  public boolean isOverrideSystemProperties() {
+    return overrideSystemProperties;
+  }
+
   private void initPropertyNamesCacheEnabled() {
     propertyNamesCacheEnabled = getPropertyBoolean(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE,
             ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE_ENVIRONMENT_VARIABLES,
@@ -428,6 +434,12 @@ public class ConfigUtil {
             propertyFileCacheEnabled);
   }
 
+  private void initOverrideSystemProperties() {
+    overrideSystemProperties = getPropertyBoolean(ApolloClientSystemConsts.APOLLO_OVERRIDE_SYSTEM_PROPERTIES,
+            ApolloClientSystemConsts.APOLLO_OVERRIDE_SYSTEM_PROPERTIES,
+            overrideSystemProperties);
+  }
+
   private boolean getPropertyBoolean(String propertyName, String envName, boolean defaultVal) {
     String enablePropertyNamesCache = System.getProperty(propertyName);
     if (Strings.isNullOrEmpty(enablePropertyNamesCache)) {

+ 7 - 0
apollo-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json

@@ -35,6 +35,13 @@
       "description": "enable apollo initialization before logging system initialization.",
       "defaultValue": false
     },
+    {
+      "name": "apollo.override-system-properties",
+      "type": "java.lang.Boolean",
+      "sourceType": "com.ctrip.framework.apollo.util.ConfigUtil",
+      "description": "enable apollo server config override system properties.",
+      "defaultValue": true
+    },
     {
       "name": "apollo.cache-dir",
       "type": "java.lang.String",

+ 27 - 0
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/boot/ApolloApplicationContextInitializerTest.java

@@ -32,6 +32,10 @@ import org.junit.Before;
 import org.junit.Test;
 import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.PropertiesPropertySource;
+import org.springframework.core.env.StandardEnvironment;
+
+import java.util.Properties;
 
 public class ApolloApplicationContextInitializerTest {
 
@@ -143,4 +147,27 @@ public class ApolloApplicationContextInitializerTest {
     assertTrue(propertySources.contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME));
     assertTrue(propertySources.iterator().next() instanceof CachedCompositePropertySource);
   }
+
+  @Test
+  public void testOverrideSystemProperties() {
+    Properties properties = new Properties();
+    properties.setProperty("server.port", "8080");
+    ConfigurableEnvironment environment = mock(ConfigurableEnvironment.class);
+
+    MutablePropertySources propertySources = new MutablePropertySources();
+    propertySources.addLast(new PropertiesPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, properties));
+
+    when(environment.getPropertySources()).thenReturn(propertySources);
+    when(environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES,
+            ConfigConsts.NAMESPACE_APPLICATION)).thenReturn("");
+    ConfigUtil configUtil = new ConfigUtil();
+    configUtil = spy(configUtil);
+    when(configUtil.isOverrideSystemProperties()).thenReturn(false);
+    MockInjector.setInstance(ConfigUtil.class, configUtil);
+
+    apolloApplicationContextInitializer.initialize(environment);
+
+    assertTrue(propertySources.contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME));
+    assertEquals(propertySources.iterator().next().getName(), StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
+  }
 }

+ 37 - 8
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessorTest.java

@@ -16,17 +16,19 @@
  */
 package com.ctrip.framework.apollo.spring.config;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
 
 import com.ctrip.framework.apollo.Config;
 import com.ctrip.framework.apollo.ConfigChangeListener;
+import com.ctrip.framework.apollo.build.ApolloInjector;
+import com.ctrip.framework.apollo.build.MockInjector;
+import com.ctrip.framework.apollo.core.ApolloClientSystemConsts;
+import com.ctrip.framework.apollo.core.ConfigConsts;
 import com.ctrip.framework.apollo.model.ConfigChangeEvent;
 import com.ctrip.framework.apollo.spring.AbstractSpringIntegrationTest;
 import com.ctrip.framework.apollo.spring.events.ApolloConfigChangeEvent;
+import com.ctrip.framework.apollo.util.ConfigUtil;
 import com.google.common.collect.Lists;
 import org.junit.After;
 import org.junit.Before;
@@ -34,9 +36,9 @@ import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.core.env.CompositePropertySource;
-import org.springframework.core.env.ConfigurableEnvironment;
-import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.*;
+
+import java.util.Properties;
 
 public class PropertySourcesProcessorTest extends AbstractSpringIntegrationTest {
 
@@ -122,4 +124,31 @@ public class PropertySourcesProcessorTest extends AbstractSpringIntegrationTest
     ApolloConfigChangeEvent event = eventCaptor.getValue();
     assertSame(someConfigChangeEvent, event.getConfigChangeEvent());
   }
+
+
+  @Test
+  public void testOverrideSystemProperties() {
+    Properties properties = new Properties();
+    properties.setProperty("server.port", "8080");
+    properties.setProperty(ApolloClientSystemConsts.APOLLO_OVERRIDE_SYSTEM_PROPERTIES, "false");
+    ConfigurableEnvironment environment = mock(ConfigurableEnvironment.class);
+
+    MutablePropertySources propertySources = new MutablePropertySources();
+    propertySources.addLast(new PropertiesPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, properties));
+
+    when(environment.getPropertySources()).thenReturn(propertySources);
+    when(environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES,
+            ConfigConsts.NAMESPACE_APPLICATION)).thenReturn("");
+
+    ConfigUtil configUtil = new ConfigUtil();
+    configUtil = spy(configUtil);
+    when(configUtil.isOverrideSystemProperties()).thenReturn(false);
+    MockInjector.setInstance(ConfigUtil.class, configUtil);
+
+    processor.setEnvironment(environment);
+    processor.postProcessBeanFactory(beanFactory);
+
+    assertTrue(propertySources.contains(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME));
+    assertEquals(propertySources.iterator().next().getName(), StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
+  }
 }

+ 5 - 0
apollo-core/src/main/java/com/ctrip/framework/apollo/core/ApolloClientSystemConsts.java

@@ -156,4 +156,9 @@ public class ApolloClientSystemConsts {
    * enable property names cache environment variables
    */
   public static final String APOLLO_CACHE_FILE_ENABLE_ENVIRONMENT_VARIABLES = "APOLLO_CACHE_FILE_ENABLE";
+
+  /**
+   * enable apollo overrideSystemProperties
+   */
+  public static final String APOLLO_OVERRIDE_SYSTEM_PROPERTIES = "apollo.override-system-properties";
 }

+ 18 - 0
docs/en/usage/java-sdk-user-guide.md

@@ -396,6 +396,24 @@ The file location reference is as follows.
 
 > Note: apollo.label is a label used to identify the application identity in the format string.
 
+#### 1.2.4.8 Enable Apollo Override System Properties
+
+> For version 2.1.0 and above
+
+Flag to indicate that Apollo's remote properties should override system properties. Default true.
+
+The configuration methods, in descending order of priority, are
+
+1. Via the Java System Property `apollo.override-system-properties`
+    * Can be specified via Java's System Property `apollo.override-system-properties`
+    * You can specify `-Dapollo.override-system-properties=true` in the Java program startup script
+        * If you are running a jar file, you need to note that the format is `java -Dapollo.override-system-properties=true -jar xxx.jar`
+    * You can also specify it programmatically, such as `System.setProperty("apollo.override-system-properties", "true");`
+2. Via the Spring Boot configuration file
+    * You can specify `apollo.override-system-properties=true` in Spring Boot's `application.properties` or `bootstrap.properties`
+3. Via the `app.properties` configuration file
+    * You can specify `apollo.override-system-properties=true` in `classpath:/META-INF/app.properties`
+
 # II. Maven Dependency
 
 Apollo's client jar package has been uploaded to the central repository, the application only needs to be introduced in the following way when it is actually used.

+ 17 - 0
docs/zh/usage/java-sdk-user-guide.md

@@ -381,6 +381,23 @@ apollo.label=YOUR-APOLLO-LABEL
 
 > 注:apollo.label是用来标识应用身份的标签,格式为string。
 
+#### 1.2.4.8 覆盖系统属性
+
+> 适用于2.1.0及以上版本
+
+`apollo.override-system-properties` 标识Apollo的远程属性是否应该覆盖Java的系统属性。默认为 true。
+
+配置方式按照优先级从高到低分别为:
+1. 通过Java System Property `apollo.override-system-properties`
+    * 可以通过Java的System Property `apollo.override-system-properties`来指定
+    * 在Java程序启动脚本中,可以指定`-Dapollo.override-system-properties=true`
+        * 如果是运行jar文件,需要注意格式是`java -Dapollo.override-system-properties=true -jar xxx.jar`
+    * 也可以通过程序指定,如`System.setProperty("apollo.override-system-properties", "true");`
+2. 通过Spring Boot的配置文件
+    * 可以在Spring Boot的`application.properties`或`bootstrap.properties`中指定`apollo.override-system-properties=true`
+3. 通过`app.properties`配置文件
+    * 可以在`classpath:/META-INF/app.properties`指定`apollo.override-system-properties=true`
+
 # 二、Maven Dependency
 Apollo的客户端jar包已经上传到中央仓库,应用在实际使用时只需要按照如下方式引入即可。
 ```xml