注入配置


在开发应用程序时,经常需要读取配置文件。最常用的配置方法是以key=value的形式写在.properties文件中。

例如,MailService根据配置的app.zone=Asia/Shanghai来决定使用哪个时区。要读取配置文件,我们可以使用上一节讲到的Resource来读取位于classpath下的一个app.properties文件。但是,这样仍然比较繁琐。

Spring容器还提供了一个更简单的@PropertySource来自动读取配置文件。我们只需要在@Configuration配置类上再添加一个注解:

  1. @Configuration
  2. @ComponentScan
  3. @PropertySource("app.properties") // 表示读取classpath的app.properties
  4. public class AppConfig {
  5. @Value("${app.zone:Z}")
  6. String zoneId;
  7. @Bean
  8. ZoneId createZoneId() {
  9. return ZoneId.of(zoneId);
  10. }
  11. }

Spring容器看到@PropertySource("app.properties")注解后,自动读取这个配置文件,然后,我们使用@Value正常注入:

  1. @Value("${app.zone:Z}")
  2. String zoneId;

注意注入的字符串语法,它的格式如下:

  • "${app.zone}"表示读取key为app.zone的value,如果key不存在,启动将报错;
  • "${app.zone:Z}"表示读取key为app.zone的value,但如果key不存在,就使用默认值Z

这样一来,我们就可以根据app.zone的配置来创建ZoneId

还可以把注入的注解写到方法参数中:

  1. @Bean
  2. ZoneId createZoneId(@Value("${app.zone:Z}") String zoneId) {
  3. return ZoneId.of(zoneId);
  4. }

可见,先使用@PropertySource读取配置文件,然后通过@Value${key:defaultValue}的形式注入,可以极大地简化读取配置的麻烦。

另一种注入配置的方式是先通过一个简单的JavaBean持有所有的配置,例如,一个SmtpConfig

  1. @Component
  2. public class SmtpConfig {
  3. @Value("${smtp.host}")
  4. private String host;
  5. @Value("${smtp.port:25}")
  6. private int port;
  7. public String getHost() {
  8. return host;
  9. }
  10. public int getPort() {
  11. return port;
  12. }
  13. }

然后,在需要读取的地方,使用#{smtpConfig.host}注入:

  1. @Component
  2. public class MailService {
  3. @Value("#{smtpConfig.host}")
  4. private String smtpHost;
  5. @Value("#{smtpConfig.port}")
  6. private int smtpPort;
  7. }

注意观察#{}这种注入语法,它和${key}不同的是,#{}表示从JavaBean读取属性。"#{smtpConfig.host}"的意思是,从名称为smtpConfig的Bean读取host属性,即调用getHost()方法。一个Class名为SmtpConfig的Bean,它在Spring容器中的默认名称就是smtpConfig,除非用@Qualifier指定了名称。

使用一个独立的JavaBean持有所有属性,然后在其他Bean中以#{bean.property}注入的好处是,多个Bean都可以引用同一个Bean的某个属性。例如,如果SmtpConfig决定从数据库中读取相关配置项,那么MailService注入的@Value("#{smtpConfig.host}")仍然可以不修改正常运行。

练习

注入配置 - 图1下载练习:注入SMTP配置 (推荐使用IDE练习插件快速下载)

小结

Spring容器可以通过@PropertySource自动读取配置,并以@Value("${key}")的形式注入;

可以通过${key:defaultValue}指定默认值;

#{bean.property}形式注入时,Spring容器自动把指定Bean的指定属性值注入。

读后有收获可以支付宝请作者喝咖啡:

注入配置 - 图2