springboot版本2.2.6

一.项目或多或少都需要一些初始化基础配置,使用配置,我们不得不考虑以下问题:什么格式、存储在哪、怎么解析、怎么加载进容器、怎么无状态灵活切换?spring是怎么做的,完整流程是怎样的?

二、资源配置流程

1.prepareEnvironment准备环境阶段,创建StandardServletEnvironment对象

1)调用StandardServletEnvironment无参构造方法,类属性MutablePropertySources propertySources实例化资源集合,类属性ConfigurablePropertyResolver propertyResolver  = new PropertySourcesPropertyResolver(this.propertySources)实例化资源解析工具;实例化三个对象:环境、资源集合、解析资源工具

2)构造方法中调用customizePropertySources方法,填充资源配置,设置四个默认配置servletConfigInitParams(整个Web应用共享的资源)、servletContextInitParams(单个serlvet的配置)、systemProperties(JVM的配置)、systemEnvironment(操作系统的配置);正是因为配置了JVM和操作系统的配置参数,所以我们可以任意使用相关参数,如JVM的:java.vm.version、user.dir、user.name、java.home、os.name,操作系统的:OS、USERNAME、HOMEPATH、JAVA_HOME等;顺便再说一句,我们平时配置的vm options参数,像-Dtest=123,会合并收集到systemProperties(JVM的配置)中

3)configureEnvironment方法,收集启动参数中的配置(main方法args参数):以--开头的命令行参数, 保存到key为commandLineArgs的PropertySource中,不以--开头的命令行参数, 保存到key为nonOptionArgs的PropertySource中,多个参数以空格分隔;如设置多环境配置参数,--spring.profiles.active=test(注:这个key值是硬编码写死的)

4)listeners.environmentPrepared(environment)方法,SpringApplicationRunListeners对象中List<SpringApplicationRunListener> listeners列表属性是spring-boot项目/META-INF/spring.factories文件中反射出来的(key:org.springframework.boot.SpringApplicationRunListener),列有中只有一个值EventPublishingRunListener,反射实例时,构造方法中创建广播者、监听者是spring-boot项目/META-INF/spring.factories文件中(key:org.springframework.context.ApplicationListener)反射出来的对象。发布准备容器环境的事件,其中一个监听器ConfigFileApplicationListener(又同时属于EnvironmentPostProcessor环境的后置处理器,看名字应该知道,目的是对环境配置做一些后置操作)。首先加载了随机数的配置,这样,项目中可以直接使用${random.int}、${random.int(10)}等随机数相关的配置;然后加载当前激活的profile列表,如多环境application-{profile}.properties配置文件application-test.properties等;再从默认的classpath:/,classpath:/config/,file:./,file:./,config/这四个目录中查找加载配置文件,如默认的classpath:application.properties

2.prepareContext准备spring容器阶段,将环境信息StandardServletEnvironment设置成spring容器上下文ConfigurableApplicationContext的容器环境

 

3.@PropertySource、@PropertySources、@ImportResource注解可以导入配置信息,原理是BeanFactory后置处理器ConfigurationClassPostProcessor,前面文章关于@Configuration注解的时候,着重介绍过ConfigurationClassPostProcessor类,简单来说,容器刷新的时候,执行BeanFactory后置处理方法,扫描所有class,检索其中的注解信息,如果有资源配置相关的注解,解析注解中资源文件,加载进容器的全局环境中

4.配置文件格式默认支持properties和yml格式,这么多的配置文件,肯定要有优先级控制,相同的key,后面会覆盖前面的value,所以key值最好不要重复。PS:有些配置根本就用不上,加载了这么多,不用考虑内存大小,大而全真的好吗?

三.环境配置相关类图

yarn config 配资源 配置资源_spring

四.不成熟的小建议

1.配置key不要重复,相同功能的key放在一起;配置文件不要太多,安全考虑,要不要加密,要不要放在其他目录下/放在远程(配置中心,后面会介绍apollo)等

2.集中管理配置,定义配置类将@Value("${key}")注解统一集中管理起来,其他bean和这个配置类打交道,而不是到处直接使用@Value("${key}")注解,类似常量池

yarn config 配资源 配置资源_配置文件_02

3.如果要写一个读取资源配置的工具类,可以选择实现EmbeddedValueResolverAware接口,利用容器中的配置和解析工具来实现,不用自己从零开始

yarn config 配资源 配置资源_spring_03

下一篇文章,介绍@Value注解的原理