Post

Spring中的配置管理

书中,以及本博文不涉及XML的配置方式,仅涉及基于Java的配置方式。

一般在概念上存在两种形式的Configuration: BeanWritingPropertyInjection
前者配置依赖关系,后者用于注入一些具体的配置属性。

BeanWriting自然是Spring配置的核心,毕竟一切都是Bean,但用现代的基于Java配置方式来完成BeanWriting是如此自然与简单,以至于我没有什么好说的。 你想要什么注入到Spring中,就用对应的注解即可(在config中用bean,简单对象用Component,还有MVC的注解等) 。至于使用,甚至不需要显式注解,直接在构造器中添加参数即可。( 当然还有autowired等方式,不过构造器已经是最佳实践所以这里不展开了)

所以本文没有BeanWriting的内容.而是关注其他宏观的配置。

调整Spring的自动配置

Spring帮我们自动完成了很多事情,例如H2数据库的使用,我们引入依赖后没多写任何一行关于H2的代码,就可以直接使用H2数据库了。但有时,我们需要对Spring自动完成的工作做一些调整,当然这不会涵盖所有Spring完成的自动配置,只是一些最最常用的配置。

理解Spring的环境抽象

首先需要明白的是,Spring是如何处理配置属性的。

简单来说,Spring对所有不同来源的配置属性做了一个统一的抽象,所有的配置属性: 包括项目路径中的applicant配置文件,jvm配置参数,操作系统环境变量,程序启动时的命令行参数等最终都会被集成抽象为The Spring Environment Bean。然后在SpringBoot自动创建Bean的过程中,若有需要的属性便从其中获取。

由于这个特性,我们可以通过上述提到的多种方法修改Spring的配置属性,不过就目前的场景而言,最简单实用的方式就是在application.properties中添加配置信息。( 当然也支持yaml,后面均用yaml格式)

数据源

一般是

1
2
3
4
5
spring:
  datasource:
    url: jdbc:mysql://localhost/tacocloud
    username: tacodb
    password: tacopassword

Spring使用的连接池是固定的几种,如果有必要,可以手动添加自定义的连接池配置。

同时,如果存在的话,Spring默认会运行项目路径中的schema.sql和data.sql文件,用于初始化数据库。如果要自定义修改

1
2
3
4
5
6
7
8
9
spring:
  datasource:
    schema:
      - order-schema.sql
      - ingredient-schema.sql
      - taco-schema.sql
      - user-schema.sql
    data:
      - ingredients.sql

服务器

1
2
3
4
5
6
server:
  port: 8443
  ssl:
    key-store: file:///path/to/mykeys.jks
    key-store-password: letmein
    key-password: letmein

日志

Spring默认用Logback作为日志框架, 如果有非常特殊的需求,例如自定义日志的信息格式,这需要在log.xml文件中进行配置。

但一些简单的配置,例如日志的级别,可以直接在application文件中进行配置。

1
2
3
4
logging:
  level:
    root: WARN
    org.springframework.security: DEBUG

其中root是默认的日志级别,org.springframework.security是SpringSecurity的日志级别。

在配置文件中使用插值表达式来对属性进行引用

常见操作,一个属性的值引用另一个属性的值,来达到重用的效果。

1
2
greeting:
  welcome: ${spring.application.name}

插值表达式是可以直接嵌入到其他字符串中的,并不会影响其他字符串的解析。

1
2
greeting:
  welcome: You are using ${spring.application.name}

创建自定义的配置

前一节中我们只需要添加配置信息就可以让程序发生变化,但这是Spring自动配置的情况,如果我们需要自定义配置自己的类,那么就还需要做一些额外工作。

通常来说,如果需要注入多个属性值或者需要支持属性的嵌套,则可以使用@ConfigurationProperties 注解;如果只需要注入一个属性值,则可以使用@Value注解。

使用@Value注解很简单,直接在属性上添加注解即可,value设定为配置的属性名即可

1
2
@Value("${MyConfig.property}")
String someProperty;

而如果有大量的属性需要注入,那么使用@ConfigurationProperties注解会更加方便。 直接标记在类上,然后指定配置文件的前缀,然后所有的名称可以被匹配的字段属性都会被注入。 如果有代码重用的需求,一个推荐的做法是将配置属性封装到一个pojo中作为一个property对象,然后在需要的地方注入property使用其get方法获取属性值即可,这样只要维护一个pojo即可。

值得一提的是,你可以直接为pojo在代码中使用硬编码进行赋值,最终配置文件中的值会覆盖掉硬编码的值,而若没有配置则会使用硬编码的值。

1
2
3
4
5
6
7
8
9
@Component
@ConfigurationProperties(prefix="taco.orders")
@Data
public class OrderProps {
  private int properity1 = 20;
  private int properity2 = 30;
  private int properity3 = 40;
  private int properity4 = 50;
}

使用profile来管理配置多个配置文件

创建多个配置文件profile

经典做法:

创建新的 application-{profile 名称}.yml 或 application-{profile 名称}.properties
例如 application-prod.yml , application-test.yml , application-dev.yml

仅支持yaml的做法:

在同一文件中用三个连字符分隔:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
logging:
  level:
    tacos: DEBUG

---
spring:
  profiles: prod
  
  datasource:
    url: jdbc:mysql://localhost/tacocloud
    username: tacouser
    password: tacopassword

logging:
  level:
    tacos: WARN

最开始的是默认配置,后面的是prod配置,当profile为prod时,后面的配置会覆盖前面的配置。

激活使用

一种流行的做法是直接在application.yml中添加spring.profiles.active属性

1
2
3
spring:
  profiles:
    active: prod

但这种做法非常不推荐。还记得之前Spring配置环境抽象吗,其中提到的Spring将多个来源的环境集中抽象在一起,所以我们可以有多种方式来修改配置属性.

我们要配置的还是spring.profiles.active属性,但不是在applicant.yml中,而是在jvm启动参数中,或者直接在计算机的环境变量中!

1
% java -jar taco-cloud.jar --spring.profiles.active=prod
1
% export SPRING_PROFILES_ACTIVE=prod

对profile有条件的Bean的配置

需求:只有当特定profile激活时,该Bean才会被创建。

实现:使用@Profile注解

1
2
3
@Profile("dev") // 只有当dev profile激活时,该Bean才会被创建
@Profile({"dev", "qa"}) // dev 或 qa
@Profile("!prod") // 非prod
This post is licensed under CC BY 4.0 by the author.