package com.qianwen.core.launch.props;
|
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.Iterator;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.BeansException;
|
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.boot.env.PropertySourceLoader;
|
import org.springframework.core.Ordered;
|
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.MutablePropertySources;
|
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.util.ClassUtils;
|
import org.springframework.util.StringUtils;
|
|
/**
|
* 在bean初始化之前对Bean的配置元数据进行操作
|
*/
|
public class BladePropertySourcePostProcessor implements BeanFactoryPostProcessor, InitializingBean, Ordered {
|
private static final Logger log = LoggerFactory.getLogger(BladePropertySourcePostProcessor.class);
|
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
|
private final List<PropertySourceLoader> propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
|
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
log.info("BladePropertySourcePostProcessor process @BladePropertySource bean.");
|
Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(BladePropertySource.class);
|
Set<Map.Entry<String, Object>> beanEntrySet = beansWithAnnotation.entrySet();
|
if (beanEntrySet.isEmpty()) {
|
log.warn("Not found @BladePropertySource on spring bean class.");
|
return;
|
}
|
List<PropertyFile> propertyFileList = new ArrayList<>();
|
for (Map.Entry<String, Object> entry : beanEntrySet) {
|
Class<?> beanClass = ClassUtils.getUserClass(entry.getValue());
|
BladePropertySource propertySource = (BladePropertySource) AnnotationUtils.getAnnotation(beanClass, BladePropertySource.class);
|
if (propertySource != null) {
|
int order = propertySource.order();
|
boolean loadActiveProfile = propertySource.loadActiveProfile();
|
propertyFileList.add(new PropertyFile(order, propertySource.value(), loadActiveProfile));
|
}
|
}
|
Map<String, PropertySourceLoader> loaderMap = new HashMap<>(16);
|
for (PropertySourceLoader loader : this.propertySourceLoaders) {
|
String[] loaderExtensions = loader.getFileExtensions();
|
for (String extension : loaderExtensions) {
|
loaderMap.put(extension, loader);
|
}
|
}
|
List<PropertyFile> sortedPropertyList = (List) propertyFileList.stream().distinct().sorted().collect(Collectors.toList());
|
//List<PropertyFile> sortedPropertyList = propertyFileList.stream().distinct().sorted().collect(Collectors.toList());
|
ConfigurableEnvironment environment = (ConfigurableEnvironment) beanFactory.getBean(ConfigurableEnvironment.class);
|
MutablePropertySources propertySources = environment.getPropertySources();
|
String[] activeProfiles = environment.getActiveProfiles();
|
ArrayList<PropertySource> propertySourceList = new ArrayList<>();
|
for (String profile : activeProfiles) {
|
for (PropertyFile propertyFile : sortedPropertyList) {
|
if (!propertyFile.loadActiveProfile)
|
continue;
|
String extension = propertyFile.getExtension();
|
PropertySourceLoader loader = loaderMap.get(extension);
|
if (loader == null)
|
throw new IllegalArgumentException("Can't find PropertySourceLoader for PropertySource extension:" + extension);
|
String location = propertyFile.getLocation();
|
String filePath = StringUtils.stripFilenameExtension(location);
|
String profiledLocation = filePath + "-" + profile + "." + extension;
|
Resource resource = this.resourceLoader.getResource(profiledLocation);
|
loadPropertySource(profiledLocation, resource, loader, propertySourceList);
|
}
|
}
|
|
|
for (PropertyFile propertyFile : sortedPropertyList) {
|
String extension = propertyFile.getExtension();
|
PropertySourceLoader loader = loaderMap.get(extension);
|
String location = propertyFile.getLocation();
|
Resource resource = this.resourceLoader.getResource(location);
|
loadPropertySource(location, resource, loader, propertySourceList);
|
}
|
|
for (PropertySource propertySource : propertySourceList)
|
propertySources.addLast(propertySource);
|
}
|
|
private static void loadPropertySource(String location, Resource resource, PropertySourceLoader loader, List<PropertySource> sourceList) {
|
if (resource.exists()) {
|
String name = "bladePropertySource: [" + location + "]";
|
try {
|
sourceList.addAll(loader.load(name, resource));
|
} catch (IOException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
}
|
|
public void afterPropertiesSet() throws Exception {
|
log.info("BladePropertySourcePostProcessor init.");
|
}
|
|
public int getOrder() {
|
return Integer.MAX_VALUE;
|
}
|
|
|
private static class PropertyFile implements Comparable<PropertyFile> {
|
private final int order;
|
private final String location;
|
private final String extension;
|
private final boolean loadActiveProfile;
|
|
public String toString() {
|
return "BladePropertySourcePostProcessor.PropertyFile(order=" + getOrder() + ", location=" + getLocation() + ", extension=" + getExtension() + ", loadActiveProfile=" + isLoadActiveProfile() + ")";
|
}
|
|
public boolean equals(final Object o) {
|
if (o == this) {
|
return true;
|
}
|
if (o instanceof PropertyFile) {
|
PropertyFile other = (PropertyFile) o;
|
if (other.canEqual(this) && getOrder() == other.getOrder() && isLoadActiveProfile() == other.isLoadActiveProfile()) {
|
Object this$location = getLocation();
|
Object other$location = other.getLocation();
|
if (this$location == null) {
|
if (other$location != null) {
|
return false;
|
}
|
} else if (!this$location.equals(other$location)) {
|
return false;
|
}
|
Object this$extension = getExtension();
|
Object other$extension = other.getExtension();
|
return this$extension == null ? other$extension == null : this$extension.equals(other$extension);
|
}
|
return false;
|
}
|
return false;
|
}
|
|
protected boolean canEqual(final Object other) {
|
return other instanceof PropertyFile;
|
}
|
|
public int hashCode() {
|
int PRIME = 59;
|
int result = 1;
|
result = result * 59 + getOrder();
|
result = result * 59 + (isLoadActiveProfile() ? 79 : 97);
|
Object $location = getLocation();
|
result = result * 59 + (($location == null) ? 43 : $location.hashCode());
|
Object $extension = getExtension();
|
return result * 59 + (($extension == null) ? 43 : $extension.hashCode());
|
}
|
|
public int getOrder() {
|
return this.order;
|
}
|
|
public String getLocation() {
|
return this.location;
|
}
|
|
public String getExtension() {
|
return this.extension;
|
}
|
|
public boolean isLoadActiveProfile() {
|
return this.loadActiveProfile;
|
}
|
|
PropertyFile(int order, String location, boolean loadActiveProfile) {
|
this.order = order;
|
this.location = location;
|
this.loadActiveProfile = loadActiveProfile;
|
this.extension = (String) Objects.requireNonNull(StringUtils.getFilenameExtension(location));
|
}
|
|
@Override
|
public int compareTo(PropertyFile other) {
|
return Integer.compare(this.order, other.order);
|
}
|
}
|
}
|