首页 > 编程语言 >springboot源码剖析(三) 环境配置

springboot源码剖析(三) 环境配置

时间:2022-10-30 16:22:14浏览次数:44  
标签:environment springboot 配置文件 配置 ConfigurableEnvironment 剖析 源码 new final

  概念

           springboot在启动流程中会把环境配置都加载进应用当中。


  实现原理

          使用环境配置器用来加载和解析所有配置文件。配置文件会被抽象成PropertySource对象存储。

     uml类图

     环境配置流程

 


  源码剖析  

           环境配置

/** SpringApplication.class 环境配置 **/
// 配置入口
public ConfigurableApplicationContext run(String... args) {
    // ...
    // 解析命令行参数
     ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    // ★解析配置文件
    ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
    // ...
}
// 解析配置文件
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    // 1.获取环境配置器
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    // ★2.环境配置器配置
    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    // 环境配置器配置文件列表加ConfigurationPropertySources类
    ConfigurationPropertySources.attach((Environment)environment);
    // ★3.事件发布器:通知监听者环境准备好了(监听者主要是加配置文件)
    // 其中ConfigFileApplicationListener加载了yml文件和中间件的配置
    listeners.environmentPrepared((ConfigurableEnvironment)environment);
    // 4.spring类绑定source属性(我的没绑到符合的)
    this.bindToSpringApplication((ConfigurableEnvironment)environment);
    // 5.不标准的环境配置器类会被强转成标准类
    if (!this.isCustomEnvironment) {
        environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
    }
    // 6.绑定source属性
    ConfigurationPropertySources.attach((Environment)environment);
    return (ConfigurableEnvironment)environment;
}
// 1.获取环境配置器
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    } else {
        // 由web应用类型决定,服务器是StandardServletEnvironment类
        switch(this.webApplicationType) {
        case SERVLET:
            // 服务器为StandardServletEnvironment,构造会初始化资源解析器和读取定制化配置文件
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
        }
    }
}
// 2.环境配置器配置
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    // 给环境配置器的资源解析器设置转换服务
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService)conversionService);
    }
    // 命令行参数添加到配置文件列表
    this.configurePropertySources(environment, args);
    // 设置动态开发环境
    this.configureProfiles(environment, args);
}

  环境配置器

/** StandardServletEnvironment.class 环境配置器 */
public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
    // 定制配置文件加载
    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
        propertySources.addLast(new StubPropertySource("servletContextInitParams"));
        if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
            propertySources.addLast(new JndiPropertySource("jndiProperties"));
        }
    
        super.customizePropertySources(propertySources);
    }
}
/** AbstractEnvironment.class 环境配置器基类 */
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
    public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";
    public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
    public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";
    protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";
    protected final Log logger = LogFactory.getLog(this.getClass());
    // 动态开发环境
    private final Set<String> activeProfiles = new LinkedHashSet();
    // 默认开发环境
    private final Set<String> defaultProfiles = new LinkedHashSet(this.getReservedDefaultProfiles());
    // 配置文件列表
    private final MutablePropertySources propertySources = new MutablePropertySources();
    // 资源解析器
    private final ConfigurablePropertyResolver propertyResolver;
    // 构造:实例化一个资源解析器,将定制化资源加载到配置文件列表中
    public AbstractEnvironment() {
        this.propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);
        this.customizePropertySources(this.propertySources);
    }
}       
/** MutablePropertySources.class 配置文件列表 */
public class MutablePropertySources implements PropertySources {
    // 配置文件都会被抽象成对象放在这里
    private final List<PropertySource<?>> propertySourceList;
}

 

      

标签:environment,springboot,配置文件,配置,ConfigurableEnvironment,剖析,源码,new,final
From: https://www.cnblogs.com/Duikerdd/p/16841436.html

相关文章

  • springboot2
    学习文档:https://blog.csdn.net/ttxbgjj/article/details/122881011---尚硅谷课程笔记https://www.yuque.com/atguigu/springboot  ---尚硅谷官网文档学习视频:https:......
  • springboot源码剖析(二) 事件发布
    概念      springboot在启动流程中会发布一些事件通知依赖组件进行主动更新。      原理是springboot使用到的一种设计模式:观察者模式。优......
  • Spring源码-context:component-scan解析
    调用AbstractApplicationContext.refresh()刷新容器,会调用obtainFreshBeanFactory()获取ConfigurableListableBeanFactory。会去调用loadBeanDefinitions()方法解析xml文件......
  • springboot源码剖析(一) 总体启动流程
    前言  之前阅读STL(C++)源码的时候,有所感悟:大佬的代码总会实践到部分设计模式、新型语法特性,亦或是精巧的算法和数据结构。     读源码的技巧:大......
  • Spring源码分析之AOP
    AOP是什么面向切面的程序设计(Aspect-orientedprogramming,AOP,又译作面向方面的程序设计、剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进......
  • SpringMVC源码-DispatcherServlet初始化
    web容器启动后会实例化Servlet,会执行Servlet的init方法且只会执行一次。后续调用doService处理客户请求。DispatcherServlet的构造方法publicDispatcherServlet(){ su......
  • 第四章 SpringBoot 底层机制
    搭建SpringBoot底层机制开发环境1、创建Maven项目lzw-springboot2、导入相关依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.o......
  • Springboot centos7 启动
     1、java-jardemo.jar说明:用这种方法启动后,不能继续执行其它命令了,如果想要继续执行其它命令,就都打断,打断一般用ctrl+c。2、java-jardemo.jar&第2种在第1种方式的基础......
  • redisson分布式限流[RRateLimiter]源码分析
    接下来在讲一讲平时用的比较多的限流模块--RRateLimiter1.简单使用publicstaticvoidmain(String[]args)throwsInterruptedException{RRateLimiterrateLimit......
  • SpringBoot3.x原生镜像-Native Image尝鲜
    前提Spring团队致力于为Spring应用程序提供原生映像支持已经有一段时间了。在SpringBoo2.x的SpringNative实验项目中酝酿了3年多之后,随着SpringFramework6和SpringBoo......