Spring 專案中讀取外部設定檔是基礎技能。本文系統整理四種主流方式:PropertiesFactoryBean (XML)、@PropertySource + Environment (注解)、@ConfigurationProperties (型別安全綁定)、Resource 直接讀取,並說明適用場景與優缺點比較。
<bean id="configProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:jdbc.properties"/>
<!-- 多檔案合併
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property> -->
<property name="ignoreResourceNotFound" value="true"/>
<property name="fileEncoding" value="UTF-8"/>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Properties props = (Properties) ctx.getBean("configProperties");
String driver = props.getProperty("jdbc.driverClassName");
@Configuration
@PropertySource(value = "classpath:jdbc.properties", encoding = "UTF-8")
public class AppConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName(env.getProperty("jdbc.driverClassName"));
ds.setJdbcUrl(env.getProperty("jdbc.url"));
ds.setUsername(env.getProperty("jdbc.username"));
ds.setPassword(env.getProperty("jdbc.password"));
return ds;
}
}
@PropertySource(value = {
"classpath:application-${spring.profiles.active}.properties",
"classpath:application.properties" // 共用預設值
}, encoding = "UTF-8", ignoreResourceNotFound = true)
jdbc.driver-class-name=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=secret
jdbc.pool.max-size=20
@Configuration
@ConfigurationProperties(prefix = "jdbc")
@PropertySource("classpath:jdbc.properties")
public class JdbcProperties {
private String driverClassName;
private String url;
private String username;
private String password;
private Pool pool = new Pool();
// Getter/Setter...
public static class Pool {
private int maxSize;
// Getter/Setter...
}
}
@EnableConfigurationProperties(JdbcProperties.class)
@SpringBootApplication
public class Application { ... }
注入使用:@Autowired JdbcProperties jdbcProps;
Resource resource = new ClassPathResource("config/test.txt");
try (InputStream is = resource.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String content = br.lines().collect(Collectors.joining("\n"));
System.out.println(content);
}
<bean id="resourceBean" class="com.example.ResourceBean">
<property name="resource" value="classpath:/config/test.txt"/>
</bean>
public class ResourceBean {
private Resource resource;
// Getter/Setter
public void printContent() throws IOException {
try (InputStream is = resource.getInputStream()) {
System.out.println(new String(is.readAllBytes(), StandardCharsets.UTF_8));
}
}
}
| 方式 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| PropertiesFactoryBean | 純 XML、無侵入、支援合併多檔 | 需手動轉型、無型別安全、重構困難 | 舊專案維護、純 XML 配置 |
| @PropertySource + Environment | 型別安全(getProperty)、支援 SpEL、多環境 | 屬性分散、無巢狀結構支援 | 中小專案、快速原型 |
| @ConfigurationProperties | 強型別、IDE 提示、驗證(JSR-303)、巢狀物件 | 需 Spring Boot 或額外啟用、類別膨脹 | Spring Boot 專案、大型專案 |
| Resource 直接讀取 | 完全控制、非 Properties 格式(JSON/YAML/純文字) | 手動解析、無熱重載、無型別轉換 | 讀取模板、腳本、證書、任意二進位 |
Spring Boot 內建支援 application.yml;傳統 Spring 需自行添加 YamlPropertySourceFactory:
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
return new PropertiesPropertySource(name, factory.getObject());
}
}
@PropertySource(value = "classpath:config.yml", factory = YamlPropertySourceFactory.class)
@Configuration
public class YamlConfig { ... }
application.properties 修改即時生效。spring-cloud-config-server 支援 {cipher} 前綴,或使用 jasypt-spring-boot。@PropertySource、PropertiesFactoryBean 明確指定 encoding="UTF-8"。