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 propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader()); public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { log.info("BladePropertySourcePostProcessor process @BladePropertySource bean."); Map beansWithAnnotation = beanFactory.getBeansWithAnnotation(BladePropertySource.class); Set> beanEntrySet = beansWithAnnotation.entrySet(); if (beanEntrySet.isEmpty()) { log.warn("Not found @BladePropertySource on spring bean class."); return; } List propertyFileList = new ArrayList<>(); for (Map.Entry 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 loaderMap = new HashMap<>(16); for (PropertySourceLoader loader : this.propertySourceLoaders) { String[] loaderExtensions = loader.getFileExtensions(); for (String extension : loaderExtensions) { loaderMap.put(extension, loader); } } List sortedPropertyList = (List) propertyFileList.stream().distinct().sorted().collect(Collectors.toList()); //List sortedPropertyList = propertyFileList.stream().distinct().sorted().collect(Collectors.toList()); ConfigurableEnvironment environment = (ConfigurableEnvironment) beanFactory.getBean(ConfigurableEnvironment.class); MutablePropertySources propertySources = environment.getPropertySources(); String[] activeProfiles = environment.getActiveProfiles(); ArrayList 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 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 { 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); } } }