Commit ac2baee2 authored by Luan Louis's avatar Luan Louis Committed by louluan

增加EnvironmentPostProcessor处理,将Apollo配置加载提到初始化日志系统之前

parent 7b19853d
...@@ -8,14 +8,17 @@ import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; ...@@ -8,14 +8,17 @@ import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import com.ctrip.framework.apollo.spring.util.SpringInjector; import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import java.util.List;
/** /**
* Initialize apollo system properties and inject the Apollo config in Spring Boot bootstrap phase * Initialize apollo system properties and inject the Apollo config in Spring Boot bootstrap phase
* *
...@@ -37,9 +40,23 @@ import org.springframework.core.env.ConfigurableEnvironment; ...@@ -37,9 +40,23 @@ import org.springframework.core.env.ConfigurableEnvironment;
* # will inject 'application' and 'FX.apollo' namespaces in bootstrap phase * # will inject 'application' and 'FX.apollo' namespaces in bootstrap phase
* apollo.bootstrap.namespaces = application,FX.apollo * apollo.bootstrap.namespaces = application,FX.apollo
* </pre> * </pre>
*
*
* If you want to load Apollo configurations even before Logging System Initialization Phase,
* add
* <pre class="code">
* # set apollo.bootstrap.eagerLoad.enabled
* apollo.bootstrap.eagerLoad.enabled = true
* </pre>
*
* This would be very helpful when your logging configurations is set by Apollo.
*
* for example, you have defined logback-spring.xml in your project , and you want to inject some attributes into logback-spring.xml.
*
*
*/ */
public class ApolloApplicationContextInitializer implements public class ApolloApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> { ApplicationContextInitializer<ConfigurableApplicationContext> , EnvironmentPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class); private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class);
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
private static final String[] APOLLO_SYSTEM_PROPERTIES = {"app.id", ConfigConsts.APOLLO_CLUSTER_KEY, private static final String[] APOLLO_SYSTEM_PROPERTIES = {"app.id", ConfigConsts.APOLLO_CLUSTER_KEY,
...@@ -61,6 +78,20 @@ public class ApolloApplicationContextInitializer implements ...@@ -61,6 +78,20 @@ public class ApolloApplicationContextInitializer implements
} }
logger.debug("Apollo bootstrap config is enabled for context {}", context); logger.debug("Apollo bootstrap config is enabled for context {}", context);
initialize(environment);
}
/**
*
*
* Initialize Apollo Configurations Just after environment is ready.
*
*
* @param environment
*/
protected void initialize(ConfigurableEnvironment environment) {
if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) { if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
//already initialized //already initialized
return; return;
...@@ -102,4 +133,39 @@ public class ApolloApplicationContextInitializer implements ...@@ -102,4 +133,39 @@ public class ApolloApplicationContextInitializer implements
System.setProperty(propertyName, propertyValue); System.setProperty(propertyName, propertyValue);
} }
/**
*
* In order to load Apollo configurations even as early before Spring loading logging system phase,
*
* This EnvironmentPostProcessor can be called Just After ConfigFileApplicationListener has succeeded.
*
*
* The processing sequence would be like this:
*
* Load Bootstrap properties and application properties -----> load Apollo configuration properties ----> Initialize Logging systems
*
*
*
* @param configurableEnvironment
* @param springApplication
*/
@Override
public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) {
Boolean eagerLoadEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED,Boolean.class,false);
//EnvironmentPostProcessor should not be triggered if you don't want Apollo Loading before Logging System Initialization
if(!eagerLoadEnabled){
return;
}
Boolean bootstrapEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED,Boolean.class,false);
if(bootstrapEnabled) {
initialize(configurableEnvironment);
}
}
} }
...@@ -4,5 +4,6 @@ public interface PropertySourcesConstants { ...@@ -4,5 +4,6 @@ public interface PropertySourcesConstants {
String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources"; String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources";
String APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME = "ApolloBootstrapPropertySources"; String APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME = "ApolloBootstrapPropertySources";
String APOLLO_BOOTSTRAP_ENABLED = "apollo.bootstrap.enabled"; String APOLLO_BOOTSTRAP_ENABLED = "apollo.bootstrap.enabled";
String APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED = "apollo.bootstrap.eagerLoad.enabled";
String APOLLO_BOOTSTRAP_NAMESPACES = "apollo.bootstrap.namespaces"; String APOLLO_BOOTSTRAP_NAMESPACES = "apollo.bootstrap.namespaces";
} }
...@@ -2,3 +2,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ...@@ -2,3 +2,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration
org.springframework.context.ApplicationContextInitializer=\ org.springframework.context.ApplicationContextInitializer=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
org.springframework.boot.env.EnvironmentPostProcessor=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
package com.ctrip.framework.apollo.spring; package com.ctrip.framework.apollo.spring;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig; import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants; import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
...@@ -20,12 +18,21 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -20,12 +18,21 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
...@@ -265,6 +272,48 @@ public class BootstrapConfigTest { ...@@ -265,6 +272,48 @@ public class BootstrapConfigTest {
} }
} }
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ConfigurationWithoutConditionalOnProperty.class)
@DirtiesContext
public static class TestWithBootstrapEnabledAndEagerLoadEnabled extends
AbstractSpringIntegrationTest {
@BeforeClass
public static void beforeClass() {
doSetUp();
System.setProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, "true");
System.setProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED, "true");
Config config = mock(Config.class);
mockConfig(ConfigConsts.NAMESPACE_APPLICATION, config);
}
@AfterClass
public static void afterClass() {
System.clearProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED);
System.clearProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED);
doTearDown();
}
@Test
public void test() {
List<EnvironmentPostProcessor> processorList = SpringFactoriesLoader.loadFactories(EnvironmentPostProcessor.class, getClass().getClassLoader());
Boolean containsApollo = !Collections2.filter(processorList, new Predicate<EnvironmentPostProcessor>() {
@Override
public boolean apply(EnvironmentPostProcessor input) {
return input instanceof ApolloApplicationContextInitializer;
}
}).isEmpty();
Assert.assertTrue(containsApollo);
}
}
@EnableAutoConfiguration @EnableAutoConfiguration
@Configuration @Configuration
static class ConfigurationWithoutConditionalOnProperty { static class ConfigurationWithoutConditionalOnProperty {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment