共计 1813 个字符,预计需要花费 5 分钟才能阅读完成。
在开发应用程序时,经常需要读取配置文件。最常用的配置方法是以 key=value
的形式写在 .properties
文件中。
例如,MailService
根据配置的 app.zone=Asia/Shanghai
来决定使用哪个时区。要读取配置文件,我们可以使用上一节讲到的 Resource
来读取位于 classpath 下的一个 app.properties
文件。但是,这样仍然比较繁琐。
Spring 容器还提供了一个更简单的 @PropertySource
来自动读取配置文件。我们只需要在 @Configuration
配置类上再添加一个注解:
@Configuration
@ComponentScan
@PropertySource("app.properties") // 表示读取 classpath 的 app.properties
public class AppConfig {@Value("${app.zone:Z}")
String zoneId;
@Bean
ZoneId createZoneId() {return ZoneId.of(zoneId);
}
}
Spring 容器看到 @PropertySource("app.properties")
注解后,自动读取这个配置文件,然后,我们使用 @Value
正常注入:
@Value("${app.zone:Z}")
String zoneId;
注意注入的字符串语法,它的格式如下:
"${app.zone}"
表示读取 key 为app.zone
的 value,如果 key 不存在,启动将报错;"${app.zone:Z}"
表示读取 key 为app.zone
的 value,但如果 key 不存在,就使用默认值Z
。
这样一来,我们就可以根据 app.zone
的配置来创建ZoneId
。
还可以把注入的注解写到方法参数中:
@Bean
ZoneId createZoneId(@Value("${app.zone:Z}") String zoneId) {return ZoneId.of(zoneId);
}
可见,先使用 @PropertySource
读取配置文件,然后通过 @Value
以${key:defaultValue}
的形式注入,可以极大地简化读取配置的麻烦。
另一种注入配置的方式是先通过一个简单的 JavaBean 持有所有的配置,例如,一个SmtpConfig
:
@Component
public class SmtpConfig {@Value("${smtp.host}")
private String host;
@Value("${smtp.port:25}")
private int port;
public String getHost() {return host;
}
public int getPort() {return port;
}
}
然后,在需要读取的地方,使用 #{smtpConfig.host}
注入:
@Component
public class MailService {@Value("#{smtpConfig.host}")
private String smtpHost;
@Value("#{smtpConfig.port}")
private int smtpPort;
}
注意观察 #{}
这种注入语法,它和 ${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}")
仍然可以不修改正常运行。
练习
注入 SMTP 配置。
下载练习
小结
Spring 容器可以通过 @PropertySource
自动读取配置,并以 @Value("${key}")
的形式注入;
可以通过 ${key:defaultValue}
指定默认值;
以 #{bean.property}
形式注入时,Spring 容器自动把指定 Bean 的指定属性值注入。