Skip to content

Commit

Permalink
fix apollo config data loader with profiles (apolloconfig#3870)
Browse files Browse the repository at this point in the history
* fix apollo config data loader with profiles

* CHANGES.md

* m_pureApolloConfig default to false

* rename field

* divide Config to 2 class

* add unit test

* change getPropertyFromRepository

* change getPropertyFromAdditional

* use spi to create PureApolloConfig, and remove the pureApolloConfig field

* modify unit test

* update getPropertyNames

* move to apollo-client-config-data

* extends DefaultConfig

* update unit test

* fix getPropertyNames

* update DefaultConfig unit test

* remove AbstractRepositoryConfig

* Update apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java

Co-authored-by: Jason Song <[email protected]>

Co-authored-by: Jason Song <[email protected]>
  • Loading branch information
vdiskg and nobodyiam authored Aug 10, 2021
1 parent 8c0241c commit 2c9b4dc
Show file tree
Hide file tree
Showing 14 changed files with 523 additions and 88 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Apollo 1.9.0
* [add spring configuration metadata for property names cache](https://github.com/ctripcorp/apollo/pull/3879)
* [Fix Multiple PropertySourcesPlaceholderConfigurer beans registered issue](https://github.com/ctripcorp/apollo/pull/3865)
* [use jdk 8 to publish apollo-client-config-data](https://github.com/ctripcorp/apollo/pull/3880)
* [fix apollo config data loader with profiles](https://github.com/ctripcorp/apollo/pull/3870)

------------------
All issues and pull requests are [here](https://github.com/ctripcorp/apollo/milestone/6?closed=1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
import com.ctrip.framework.apollo.config.data.extension.initialize.ApolloClientExtensionInitializer;
import com.ctrip.framework.apollo.config.data.extension.properties.ApolloClientProperties;
import com.ctrip.framework.apollo.config.data.extension.webclient.customizer.spi.ApolloClientWebClientCustomizerFactory;
import com.ctrip.framework.apollo.config.data.extension.webclient.injector.ApolloClientCustomHttpClientInjectorCustomizer;
import com.ctrip.framework.apollo.config.data.injector.ApolloConfigDataInjectorCustomizer;
import com.ctrip.framework.apollo.util.http.HttpClient;
import com.ctrip.framework.foundation.internals.ServiceBootstrap;
import java.util.List;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -62,6 +63,7 @@ public void initialize(ApolloClientProperties apolloClientProperties, Binder bin
}
}
}
ApolloClientCustomHttpClientInjectorCustomizer.setCustomWebClient(webClientBuilder.build());
HttpClient httpClient = new ApolloWebClientHttpClient(webClientBuilder.build());
ApolloConfigDataInjectorCustomizer.registerIfAbsent(HttpClient.class, () -> httpClient);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ public ConfigData load(ConfigDataLoaderContext context, ApolloConfigDataResource
List<PropertySource<?>> propertySourceList = new ArrayList<>();
propertySourceList.add(configPropertySource);
propertySourceList.addAll(initialPropertySourceList);
log.debug(Slf4jLogMessageFormatter
.format("apollo client loaded namespace [{}]", resource.getNamespace()));
log.debug(Slf4jLogMessageFormatter.format("apollo client loaded namespace [{}]", namespace));
return new ConfigData(propertySourceList);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package com.ctrip.framework.apollo.config.data.importer;

import com.ctrip.framework.apollo.config.data.extension.initialize.ApolloClientExtensionInitializeFactory;
import com.ctrip.framework.apollo.config.data.injector.ApolloConfigDataInjectorCustomizer;
import com.ctrip.framework.apollo.config.data.internals.PureApolloConfigFactory;
import com.ctrip.framework.apollo.config.data.system.ApolloClientSystemPropertyInitializer;
import com.ctrip.framework.apollo.config.data.util.Slf4jLogMessageFormatter;
import com.ctrip.framework.apollo.core.utils.DeferredLogger;
import com.ctrip.framework.apollo.spi.ConfigFactory;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -100,6 +103,8 @@ private void initApolloClientInternal() {
new ApolloClientExtensionInitializeFactory(this.log,
this.bootstrapContext).initializeExtension(this.binder, this.bindHandler);
DeferredLogger.enable();
ApolloConfigDataInjectorCustomizer.register(ConfigFactory.class,
PureApolloConfigFactory::new);
}

private boolean forceDisableApolloBootstrap() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2021 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.config.data.injector;

import com.ctrip.framework.apollo.core.spi.Ordered;
import com.ctrip.framework.apollo.spi.ApolloInjectorCustomizer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
* @author vdisk <[email protected]>
*/
public class ApolloConfigDataInjectorCustomizer implements ApolloInjectorCustomizer {

/**
* the order of the injector customizer
*/
public static final int ORDER = Ordered.LOWEST_PRECEDENCE - 200;

private static final Map<Class<?>, Supplier<?>> INSTANCE_SUPPLIERS = new ConcurrentHashMap<>();

private static final Map<Class<?>, Object> INSTANCES = new ConcurrentHashMap<>();

/**
* Register a specific type with the registry. If the specified type has already been registered,
* it will be replaced.
*
* @param <T> the instance type
* @param type the instance type
* @param instanceSupplier the instance supplier
*/
public static <T> void register(Class<T> type, Supplier<T> instanceSupplier) {
INSTANCE_SUPPLIERS.put(type, instanceSupplier);
}

/**
* Register a specific type with the registry if one is not already present.
*
* @param <T> the instance type
* @param type the instance type
* @param instanceSupplier the instance supplier
*/
public static <T> void registerIfAbsent(Class<T> type, Supplier<T> instanceSupplier) {
INSTANCE_SUPPLIERS.putIfAbsent(type, instanceSupplier);
}

/**
* Return if a registration exists for the given type.
*
* @param <T> the instance type
* @param type the instance type
* @return {@code true} if the type has already been registered
*/
public static <T> boolean isRegistered(Class<T> type) {
return INSTANCE_SUPPLIERS.containsKey(type);
}

@Override
public <T> T getInstance(Class<T> clazz) {
@SuppressWarnings("unchecked")
Supplier<T> instanceSupplier = (Supplier<T>) INSTANCE_SUPPLIERS.get(clazz);
if (instanceSupplier == null) {
return null;
}
return this.getInstance(clazz, instanceSupplier);
}

@SuppressWarnings("unchecked")
private <T> T getInstance(Class<T> type, Supplier<T> instanceSupplier) {
T instance = (T) INSTANCES.get(type);
if (instance != null) {
return instance;
}
// prebuild an newInstance to prevent dead lock when recursive call computeIfAbsent
// https://bugs.openjdk.java.net/browse/JDK-8062841
T newInstance = instanceSupplier.get();
return (T) INSTANCES.computeIfAbsent(type, key -> newInstance);
}

@Override
public <T> T getInstance(Class<T> clazz, String name) {
return null;
}

@Override
public int getOrder() {
return ORDER;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2021 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.config.data.internals;

import com.ctrip.framework.apollo.internals.ConfigRepository;
import com.ctrip.framework.apollo.internals.DefaultConfig;
import com.ctrip.framework.apollo.internals.RepositoryChangeListener;
import com.google.common.collect.Sets;
import java.util.Set;
import org.springframework.util.CollectionUtils;

/**
* @author vdisk <[email protected]>
*/
public class PureApolloConfig extends DefaultConfig implements RepositoryChangeListener {

/**
* Constructor.
*
* @param namespace the namespace of this config instance
* @param configRepository the config repository for this config instance
*/
public PureApolloConfig(String namespace,
ConfigRepository configRepository) {
super(namespace, configRepository);
}

@Override
public String getProperty(String key, String defaultValue) {
// step 1: check local cached properties file
String value = this.getPropertyFromRepository(key);

// step 2: check properties file from classpath
if (value == null) {
value = this.getPropertyFromAdditional(key);
}

this.tryWarnLog(value);

return value == null ? defaultValue : value;
}

@Override
public Set<String> getPropertyNames() {
// pure apollo config only contains the property from repository and the property from additional
Set<String> fromRepository = this.getPropertyNamesFromRepository();
Set<String> fromAdditional = this.getPropertyNamesFromAdditional();
if (CollectionUtils.isEmpty(fromRepository)) {
return fromAdditional;
}
if (CollectionUtils.isEmpty(fromAdditional)) {
return fromRepository;
}
Set<String> propertyNames = Sets
.newLinkedHashSetWithExpectedSize(fromRepository.size() + fromAdditional.size());
propertyNames.addAll(fromRepository);
propertyNames.addAll(fromAdditional);
return propertyNames;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2021 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.config.data.internals;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.internals.ConfigRepository;
import com.ctrip.framework.apollo.spi.ConfigFactory;
import com.ctrip.framework.apollo.spi.DefaultConfigFactory;

/**
* @author vdisk <[email protected]>
*/
public class PureApolloConfigFactory extends DefaultConfigFactory implements ConfigFactory {

@Override
protected Config createRepositoryConfig(String namespace, ConfigRepository configRepository) {
return new PureApolloConfig(namespace, configRepository);
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
com.ctrip.framework.apollo.config.data.extension.webclient.injector.ApolloClientCustomHttpClientInjectorCustomizer
com.ctrip.framework.apollo.config.data.injector.ApolloConfigDataInjectorCustomizer
Loading

0 comments on commit 2c9b4dc

Please sign in to comment.