Skip to content

Commit

Permalink
增加EnvironmentPostProcessor处理,将Apollo配置加载提到初始化日志系统之前
Browse files Browse the repository at this point in the history
  • Loading branch information
LuanLouis authored and louluan committed Oct 29, 2018
1 parent 7b19853 commit ac2baee
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;

import java.util.List;

/**
* Initialize apollo system properties and inject the Apollo config in Spring Boot bootstrap phase
*
Expand All @@ -37,9 +40,23 @@
* # will inject 'application' and 'FX.apollo' namespaces in bootstrap phase
* apollo.bootstrap.namespaces = application,FX.apollo
* </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
ApplicationContextInitializer<ConfigurableApplicationContext> {
ApplicationContextInitializer<ConfigurableApplicationContext> , EnvironmentPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(ApolloApplicationContextInitializer.class);
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
private static final String[] APOLLO_SYSTEM_PROPERTIES = {"app.id", ConfigConsts.APOLLO_CLUSTER_KEY,
Expand All @@ -61,6 +78,20 @@ public void initialize(ConfigurableApplicationContext 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)) {
//already initialized
return;
Expand Down Expand Up @@ -102,4 +133,39 @@ private void fillSystemPropertyFromEnvironment(ConfigurableEnvironment environme

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);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public interface PropertySourcesConstants {
String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources";
String APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME = "ApolloBootstrapPropertySources";
String APOLLO_BOOTSTRAP_ENABLED = "apollo.bootstrap.enabled";
String APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED = "apollo.bootstrap.eagerLoad.enabled";
String APOLLO_BOOTSTRAP_NAMESPACES = "apollo.bootstrap.namespaces";
}
2 changes: 2 additions & 0 deletions apollo-client/src/main/resources/META-INF/spring.factories
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration
org.springframework.context.ApplicationContextInitializer=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
org.springframework.boot.env.EnvironmentPostProcessor=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
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.core.ConfigConsts;
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.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
import org.junit.AfterClass;
import org.junit.Assert;
Expand All @@ -20,12 +18,21 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.test.annotation.DirtiesContext;
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([email protected])
*/
Expand Down Expand Up @@ -265,6 +272,48 @@ public void test() throws Exception {
}
}


@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
@Configuration
static class ConfigurationWithoutConditionalOnProperty {
Expand Down

0 comments on commit ac2baee

Please sign in to comment.