前面我们简单介绍了自动配置的实现原理,基本上流程就是配置文件标明启用什么服务,然后找到对应的依赖(class),然后结合条件装配初始化 Bean。
所以 Spring 就更进一步,按照功能模块,划分出一个个 Starter 模块。以 Maven 为例,基本上我们只需要将 Spring Boot 自己的那个 POM 文件设置为 parent,然后依赖中直接依赖所需的 Starter 坐标,即可依赖所有所需的 jar 包,剩下的的东西,仅有最基础的属性值配置。
当然 Starter 也是一把双刃剑,比如我在项目里面依赖了 spring-boot-starter-data-jpa
之后在 IDEA 里面看到的依赖树,简直就是 jar 包狂魔,虽然我们需要 jpa,但是不一定需要全部这些包。
这也就引出了我使用 Starter 的时候的几个困扰。比如项目需要以 spring-boot 的 pom 为 parent,这个就比较讨厌了,尤其是我前公司,所有的项目是同一内部的 parent,这样子可以管理大家的依赖。如果要用Spring Boot 的话,就会略有麻烦。可能就需要通过依赖 Spring Boot 的 pom 的方式,并不是很优雅。
问题二是我在用 Spring Boot 时依赖 logstash 遇到的, logstash自己依赖了一个 logback-access 和那个版本的 Spring Boot 依赖的 logback 不一致,导致一直报一个 java.lang.AssertionError
问题三就是我最近想用 Spring Boot 去读写 Kafka,结果我们用的 Kafka 版本比较老,最后只好自己配置,特别麻烦。很多老的组件,要么你得用老的 Spring Boot,要么你就得自己配置。
比如我们基于 YAML 定义了上图这么一段配置,最简单的方式就是 @Value
注解,通知这货还支持 Spring El 表达式,做一些简单的处理判断。
但是对于一个组件的配置,或者是项目自己的配置,更需要比较好的梳理,Spring Boot 便支持了所谓的 prefix 前缀的概念,我们可以把所需要的配置信息定义为一个配置类,在里面定义好必要的 Getter Setter 一类的东西。在初始化项目的时候使用 @EnableConfigurationProperties
注解即可实现配置参数注入到配置类里面。
当然麻烦的地方在于如果配置文件定义的层级过深,配置类会变得极其复杂。建议这种情况下,尽可能简化层级。
配置文件的加载,其实 Spring Boot 有一个非常复杂的流程,大家好奇的话可以看 Spring Boot 文档中的定义,大概有十几种情况。但是大部分情况下,我们用不了这么多,上面是我认为应该知道并且利用的几种情况,配置加载的顺序是由上往下。
第一种情况,和 jar 包在同一目录下,一般是应用发布到生产,然后还想修改更新配置的情况。
项目 resources 目录和 resources/config 下面的配置文件,就是我们在开发的时候会选取的存放配置的位置。
当然配置文件的名称默认是 application,还可能根据你所启用的 Profile 加载不同名称的配置文件。
由于配置文件的指定在 Spring Boot 中极其灵活,(官方可能把所有的情况都考虑到了)所以大家可以自己按需选择。
测试当然也有 Starter,我们只需要依赖 spring-boot-starter-test
,即可轻松写测试。常见的测试注解就是上面几个
@WebIntegrationTest
注解相当于 @IntegrationTest
+ @WebAppConfiguration
注解结合使用,在 1.3 之前,主要是使用前面4个注解进行测试。
1.4 之后,我们主要使用 SpringBootTest
注解做测试
讲得好!