Spring 配置管理

1.spring对众多配置的管理

      配置现在在我们的项目里面,是非常关键的一环。往往一些中间件,需要用户,修改一些配置文件,才能正常使用。我们在日常开发中,一些数据库地址,系统常量,等这些信息,都是通过配置的方式,参与到系统的运行,可以说配置和我们的软件开发蜜不可分,而java也提供了一些接口,来进行配置文件的解析。JDK只是提供了对应配置文件的基础功能的实现,但是并没有对我们的配置做整合。Spring 在JDK的基础上进行了配置的统一处理最核心的接口 PropertySource 我们每写一个配置文件 这些文件都会被加载到PropertySource抽象类的实现类中比如 我们的Springboot下application.properties  就会被加载到 PropertySource抽象类的实现类中。但是往往,一个项目的配置是比较多的,而且需要分环境管理,一个配置文件显然是不可能的,而配置的方式又可以是多种多样的。我们可能还得用到System的配置,也有可能用到操作系统环境变量的配置,还要可能是不同环境下不同文件的实现,这些等等的问题,都不可能用PropertySource一个对象来实现,所以Spring这边就用了集合PropertySources类来实现(其实就是个PropertySource的集合)。把众多的配置,放到一个集合里面进行统一管理。而Spring ApplicationContext 中通过 Environment 接口,封装了对PropertySources类的操作,屏蔽了里面对各个配置的不同的差异。那多个配置类,也带来一个问题,那就是多种配置存在的情况下,以什么为准呢?spring这边定义了一个优先级顺序的问题,当优先级越高,我们就先获得一个值,那么这个值就是我们所需要的值。其他的配置,无论是什么牛鬼蛇神,都不会理会。

2.Spring各配置的优先级

1、开发者工具 `Devtools` 全局配置参数;

2、单元测试上的 `@TestPropertySource` 注解指定的参数;

3、单元测试上的 `@SpringBootTest` 注解指定的参数;

4、命令行指定的参数,如 `java -jar springboot.jar --name="Java技术栈"`;

5、命令行中的 `SPRING_APPLICATION_JSONJSON` 指定参数, 如 `java -Dspring.application.json='{"name":"Java技术栈"}' -jar springboot.jar`

6、`ServletConfig` 初始化参数;

7、`ServletContext` 初始化参数;

8、JNDI参数(如 `java:comp/env/spring.application.json`);

9、Java系统参数(来源:`System.getProperties()`);

10、操作系统环境变量参数;

11、`RandomValuePropertySource` 随机数,仅匹配:`ramdom.*`;

12、JAR包外面的配置文件参数(`application-{profile}.properties(YAML)`)

13、JAR包里面的配置文件参数(`application-{profile}.properties(YAML)`)

14、JAR包外面的配置文件参数(`application.properties(YAML)`)

15、JAR包里面的配置文件参数(`application.properties(YAML)`)

16、`@Configuration`配置文件上 `@PropertySource` 注解加载的参数;

17、默认参数(通过 `SpringApplication.setDefaultProperties` 指定);

3.从实际项目中 得到对优先级的理解

      我曾经待过一个项目组,他的配置是集成打包环境来进行打包。在通过系统对某环境配置,然后在打包的时候,会生成对应环境的application.properties文件,同时对应的spring boot jar 会生成一个docker镜像,然后配置和镜像都发送到对应的虚拟机中。启动镜像的时候,会在宿主机某目录下找到对应的application.properties文件,通过外部的配置文件进行启动。一开始,我们对spring 外部配置完全不了解,也不知道这块的加载顺序,对项目打包也不了解。以至于,在环境中,我们打包的时候,一直没有剔除jar包内置的application.properties文件。这个时候在我们spring容器里面,其实是加载了两个配置文件,一个jar包外部配置文件,一个jar包内部配置文件。我们从上面的顺序可以知道,内置的application.properties他又是优先级比外部的高,导致了环境上真正的配置文件,从来没有生效过,给一开始的开发联调测试难度造成了巨大的困扰。后面,在环境项目组的指导下,我们通过maven工具,在打包的时候剔除了内置的application.properties文件。当时只是这么做了,但是这个问题我并没有真正的重视,并没有思考发生这种情况的原理是啥。直到最近,当前项目组里面,出现了一个问题。那就是我在引用二方包的时候,里面有项配置没有我们需要特殊修改,所以得覆盖原先包里面的配置。当时负责人,让我修改一下,做起来也简单,就是在application.properties重新定义一下就好了。当时,我还是比较懊恼的,为啥这么简单的,我想不到改。

4.从中学到的经验

      当时,我就纳闷儿了,为啥可以这样呢,为啥他知道,我不知道呢?其实就是我不理解这其中的原理,无法对及时做出正确的理解。经过这段的时间的学习,现在豁然开朗,其实就是spring用的组合配置的方式,定义优先级,来实现不同配置文件的覆盖问题,这个可能在我们日常开发中遇到的不多。但是在,遇到二方或者三方包里面,我们合理的掌握优先级,可以方便我们开发出封装度很高的代码。还有就是要善于发现身边的问题,及时研究,可以更加好的运用到实际代码中去

5.spring 这么管理的好处

      spring 对配置的统一管理,给配置的扩展带来的极大的遍历。Spring这样的封装方式,又为后续的spring Cloud 注册中心实现提供了基础。其实,配置中心的原理上,无非就是通过starter包,加载远程配置,将远程配置中的配置项,拉取到本地,最终注入到Environment对象中,这样,分布式的配置就实现了,只是不同的配置中心,客户端不一样,但是注入的方式,那肯定是一样的。

      在这里,不得不佩服,spring团队设计的合理性。因为这些核心类,都在org.springframework.core.env

包下面,以前在关注spring源码的时候,不知道core包的具体作用是啥,现在好歹接触到里面的核心模块之一。也可以看出spring 代码在设计上的合理性

你可能感兴趣的:(Spring 配置管理)