Spring之环境变量配置

本地配置实现原理

Spring之环境变量配置_第1张图片

项目启动时准备环境

public class SpringApplication {

    public ConfigurableApplicationContext run(String... args) {
        long startTime = System.nanoTime();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 获取环境变量和配置数据
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            listeners.started(context, timeTakenToStartup);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }
}

获取系统环境变量和配置数据,加载为Environment

    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = this.convertEnvironment((ConfigurableEnvironment)environment);
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

Spring之环境变量配置_第2张图片

listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);

public interface PropertySourceLoader {
    String[] getFileExtensions();

    List> load(String name, Resource resource) throws IOException;
}

spring在5个路径下(classpath/*, classpath/config/*, /*, /config/*, /config/*/*)找application.properties和application.yml配置文件。

注:默认先读取application.properties文件,如果application.properties和application.yml中有相同的属性,那么以application.properties中的值为准,一旦加载到对应的属性,后面就会跳过,不会覆盖前面加载的属性值

针对application.yml,实现类是YamlPropertySourceLoader

public class YamlPropertySourceLoader implements PropertySourceLoader {
    public YamlPropertySourceLoader() {}

    public String[] getFileExtensions() {
        return new String[]{"yml", "yaml"};
    }

    public List> load(String name, Resource resource) throws IOException {
        if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", this.getClass().getClassLoader())) {
            throw new IllegalStateException("Attempted to load " + name + " but snakeyaml was not found on the classpath");
        } else {
            List> loaded = (new OriginTrackedYamlLoader(resource)).load();
            if (loaded.isEmpty()) {
                return Collections.emptyList();
            } else {
                List> propertySources = new ArrayList(loaded.size());

                for(int i = 0; i < loaded.size(); ++i) {
                    String documentNumber = loaded.size() != 1 ? " (document #" + i + ")" : "";
                    propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)loaded.get(i)), true));
                }

                return propertySources;
            }
        }
    }
}

针对application.properties,实现类是PropertiesPropertySourceLoader

public class PropertiesPropertySourceLoader implements PropertySourceLoader {
    private static final String XML_FILE_EXTENSION = ".xml";

    public PropertiesPropertySourceLoader() {}

    public String[] getFileExtensions() {
        return new String[]{"properties", "xml"};
    }

    public List> load(String name, Resource resource) throws IOException {
        List> properties = this.loadProperties(resource);
        if (properties.isEmpty()) {
            return Collections.emptyList();
        } else {
            List> propertySources = new ArrayList(properties.size());

            for(int i = 0; i < properties.size(); ++i) {
                String documentNumber = properties.size() != 1 ? " (document #" + i + ")" : "";
                propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)properties.get(i)), true));
            }

            return propertySources;
        }
    }

    private List> loadProperties(Resource resource) throws IOException {
        String filename = resource.getFilename();
        List> result = new ArrayList();
        if (filename != null && filename.endsWith(".xml")) {
            result.add(PropertiesLoaderUtils.loadProperties(resource));
        } else {
            List documents = (new OriginTrackedPropertiesLoader(resource)).load();
            documents.forEach((document) -> {
                result.add(document.asMap());
            });
        }

        return result;
    }
}
public final class ConfigurationPropertySources {
    private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";

    public static void attach(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        MutablePropertySources sources = ((ConfigurableEnvironment)environment).getPropertySources();
        PropertySource attached = getAttached(sources);
        if (attached == null || !isUsingSources((PropertySource)attached, sources)) {
            attached = new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources));
        }
        sources.remove("configurationProperties");
        // 将加载了配置文件的PropertySource添加到Environment中
        sources.addFirst((PropertySource)attached);
    }
}

刷新上下文容器

public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext {
    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }
        this.refresh(context);
    }

    protected void refresh(ConfigurableApplicationContext applicationContext) {
        applicationContext.refresh();
    }
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }
                this.destroyBeans();
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }
}

注册BeanPostProcessors,通过BeanPostProcessor修改bean的属性值

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
}
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

    protected  T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    }
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        this.populateBean(beanName, mbd, instanceWrapper);
    }

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        PropertyValues pvsToUse;
        for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
            InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
            pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
        }
    }
}

通过BeanPostProcessor注入bean的属性

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

        try {
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }
}
public class InjectionMetadata {
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection checkedElements = this.checkedElements;
        Collection elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
        if (!((Collection)elementsToIterate).isEmpty()) {
            Iterator var6 = ((Collection)elementsToIterate).iterator();

            while(var6.hasNext()) {
                InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
                element.inject(target, beanName, pvs);
            }
        }
    }
}

AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(bean, beanName, pvs) -> resolveFieldValue(field, bean, beanName) ->

bean属性注入

        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field)this.member;
            Object value;
            if (this.cached) {
                try {
                    value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
                } catch (NoSuchBeanDefinitionException var7) {
                    value = this.resolveFieldValue(field, bean, beanName);
                }
            } else {
                // 获取字段@Value对应的值
                value = this.resolveFieldValue(field, bean, beanName);
            }

            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                // 通过反射给目标字段赋值
                field.set(bean, value);
            }
        }

获取字段的值

        @Nullable
        private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
            DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            desc.setContainingClass(bean.getClass());
            Set autowiredBeanNames = new LinkedHashSet(1);
            Assert.state(AutowiredAnnotationBeanPostProcessor.this.beanFactory != null, "No BeanFactory available");
            TypeConverter typeConverter = AutowiredAnnotationBeanPostProcessor.this.beanFactory.getTypeConverter();

            Object value;
            try {
                // 获取字段依赖的属性值
                value = AutowiredAnnotationBeanPostProcessor.this.beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            } catch (BeansException var12) {
                throw new UnsatisfiedDependencyException((String)null, beanName, new InjectionPoint(field), var12);
            }

            synchronized(this) {
                if (!this.cached) {
                    Object cachedFieldValue = null;
                    if (value != null || this.required) {
                        cachedFieldValue = desc;
                        AutowiredAnnotationBeanPostProcessor.this.registerDependentBeans(beanName, autowiredBeanNames);
                        if (autowiredBeanNames.size() == 1) {
                            String autowiredBeanName = (String)autowiredBeanNames.iterator().next();
                            if (AutowiredAnnotationBeanPostProcessor.this.beanFactory.containsBean(autowiredBeanName) && AutowiredAnnotationBeanPostProcessor.this.beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                cachedFieldValue = new AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());
                            }
                        }
                    }

                    this.cachedFieldValue = cachedFieldValue;
                    this.cached = true;
                }

                return value;
            }
        }

获取注入依赖

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return this.createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
            if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
            } else {
                Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }

                return result;
            }
        } else {
            return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
        }
    }
}
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

        Object var23;
        try {
            Object shortcut = descriptor.resolveShortcut(this);
            if (shortcut != null) {
                Object var20 = shortcut;
                return var20;
            }

            Class type = descriptor.getDependencyType();
            Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor);
            Object var11;
            if (value == null) {
                Object multipleBeans = this.resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
                if (multipleBeans != null) {
                    var23 = multipleBeans;
                    return var23;
                }

                Map matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);
                if (matchingBeans.isEmpty()) {
                    if (this.isRequired(descriptor)) {
                        this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    var11 = null;
                    return var11;
                }

                Object instanceCandidate;
                Object result;
                String autowiredBeanName;
                if (matchingBeans.size() > 1) {
                    autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
                    if (autowiredBeanName == null) {
                        if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
                            result = null;
                            return result;
                        }
                        result = descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                        return result;
                    }

                    instanceCandidate = matchingBeans.get(autowiredBeanName);
                } else {
                    Entry entry = (Entry)matchingBeans.entrySet().iterator().next();
                    autowiredBeanName = (String)entry.getKey();
                    instanceCandidate = entry.getValue();
                }

                if (autowiredBeanNames != null) {
                    autowiredBeanNames.add(autowiredBeanName);
                }
                if (instanceCandidate instanceof Class) {
                    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
                }

                result = instanceCandidate;
                if (instanceCandidate instanceof NullBean) {
                    if (this.isRequired(descriptor)) {
                        this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    result = null;
                }

                if (!ClassUtils.isAssignableValue(type, result)) {
                    throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
                }
                Object var14 = result;
                return var14;
            }

            if (value instanceof String) {
                // 获取bean注入的属性值
                String strVal = this.resolveEmbeddedValue((String)value);
                BeanDefinition bd = beanName != null && this.containsBean(beanName) ? this.getMergedBeanDefinition(beanName) : null;
                value = this.evaluateBeanDefinitionString(strVal, bd);
            }

            TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();
            try {
                var23 = converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            } catch (UnsupportedOperationException var18) {
                var11 = descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter());
                return var11;
            }
        } finally {
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }

        return var23;
    }

AbstractBeanFactory.resolveEmbeddedValue(value)

根据@Value注解的key获取对应的值

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @Nullable
    public String resolveEmbeddedValue(@Nullable String value) {
        if (value == null) {
            return null;
        } else {
            String result = value;
            Iterator var3 = this.embeddedValueResolvers.iterator();

            do {
                if (!var3.hasNext()) {
                    return result;
                }

                StringValueResolver resolver = (StringValueResolver)var3.next();
                result = resolver.resolveStringValue(result);
            } while(result != null);

            return null;
        }
    }
}

Spring之环境变量配置_第3张图片

最后通过反射给目标字段赋值

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    private class AutowiredFieldElement extends InjectedElement {
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field)this.member;
            Object value;
            if (this.cached) {
                try {
                    value = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
                } catch (NoSuchBeanDefinitionException var7) {
                    value = this.resolveFieldValue(field, bean, beanName);
                }
            } else {
                // 获取字段@Value对应的值
                value = this.resolveFieldValue(field, bean, beanName);
            }

            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                // 通过反射给目标字段赋值
                field.set(bean, value);
            }
        }
    }
}

field.set(bean, value);

public final class Field extends AccessibleObject implements Member {
    @CallerSensitive
    public void set(Object obj, Object value)
        throws IllegalArgumentException, IllegalAccessException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        getFieldAccessor(obj).set(obj, value);
    }
}

你可能感兴趣的:(Spring,spring)