package com.ctrip.framework.apollo.common.config; import com.google.common.base.Splitter; import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory; import com.ctrip.framework.apollo.tracer.Tracer; import com.google.common.base.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; public abstract class RefreshableConfig { private static final Logger logger = LoggerFactory.getLogger(RefreshableConfig.class); private static final String LIST_SEPARATOR = ","; //TimeUnit: second private static final int CONFIG_REFRESH_INTERVAL = 60; protected Splitter splitter = Splitter.on(LIST_SEPARATOR).omitEmptyStrings().trimResults(); @Autowired private ConfigurableEnvironment environment; private List<RefreshablePropertySource> propertySources; /** * register refreshable property source. * Notice: The front property source has higher priority. */ protected abstract List<RefreshablePropertySource> getRefreshablePropertySources(); @PostConstruct public void setup() { propertySources = getRefreshablePropertySources(); if (CollectionUtils.isEmpty(propertySources)) { throw new IllegalStateException("Property sources can not be empty."); } //add property source to environment for (RefreshablePropertySource propertySource : propertySources) { propertySource.refresh(); environment.getPropertySources().addLast(propertySource); } //task to update configs ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ConfigRefresher", false)); executorService .scheduleWithFixedDelay(() -> { try { propertySources.forEach(RefreshablePropertySource::refresh); } catch (Throwable t) { logger.error("Refresh configs failed.", t); Tracer.logError("Refresh configs failed.", t); } }, CONFIG_REFRESH_INTERVAL, CONFIG_REFRESH_INTERVAL, TimeUnit.SECONDS); } public int getIntProperty(String key, int defaultValue) { try { String value = getValue(key); return value == null ? defaultValue : Integer.parseInt(value); } catch (Throwable e) { Tracer.logError("Get int property failed.", e); return defaultValue; } } public boolean getBooleanProperty(String key, boolean defaultValue) { try { String value = getValue(key); return value == null ? defaultValue : "true".equals(value); } catch (Throwable e) { Tracer.logError("Get boolean property failed.", e); return defaultValue; } } public String[] getArrayProperty(String key, String[] defaultValue) { try { String value = getValue(key); return Strings.isNullOrEmpty(value) ? defaultValue : value.split(LIST_SEPARATOR); } catch (Throwable e) { Tracer.logError("Get array property failed.", e); return defaultValue; } } public String getValue(String key, String defaultValue) { try { return environment.getProperty(key, defaultValue); } catch (Throwable e) { Tracer.logError("Get value failed.", e); return defaultValue; } } public String getValue(String key) { return environment.getProperty(key); } }