Spring 提供了多層次的資源讀取抽象:從底層 org.springframework.core.io.Resource 介面,到 PropertySource 機制、@Value 注入、@ConfigurationProperties 綁定,再到 Environment 統一存取。本文梳理三種常見場景的實作方式,並說明現代 Spring Boot 專案的推薦做法。
適用於純 Spring XML 配置專案,將 .properties 暴露為 java.util.Properties Bean:
<bean id="configProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-datasource.xml");
Properties props = (Properties) ctx.getBean("configProperties");
String driver = props.getProperty("jdbcOrcale.driverClassName");
Resource 是 Spring 統一資源抽象(classpath、file、URL、ServletContext 等),適用於需讀取非 Properties 格式(如 JSON、XML、純文字)的場景。
public void readDirectly() throws IOException {
Resource resource = applicationContext.getResource("classpath:com/springdemo/resource/test.txt");
File file = resource.getFile(); // 僅當 resource 為 FileSystemResource 時可用
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[(int) file.length()];
fis.read(buffer);
String content = new String(buffer, StandardCharsets.UTF_8);
System.out.println(content);
}
}
public class ResourceBean {
private Resource resource;
// getter/setter
}
<bean id="resourceBean" class="com.springdemo.resource.ResourceBean">
<property name="resource" value="classpath:/com/springdemo/resource/test.txt"/>
</bean>
Spring Boot 2.0+ 強烈建議使用 @ConfigurationProperties 類型安全綁定,而非手動讀取 Properties。
jdbc:
oracle:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@localhost:1521:orcl
username: scott
password: tiger
@ConfigurationProperties(prefix = "jdbc.oracle")
@Data // Lombok
public class OracleJdbcProperties {
private String driverClassName;
private String url;
private String username;
private String password;
}
@Configuration
@EnableConfigurationProperties(OracleJdbcProperties.class)
public class JdbcConfig {
// 也可用 @Bean 方法註冊 DataSource
}
@Service
public class DataService {
private final OracleJdbcProperties props;
public DataService(OracleJdbcProperties props) {
this.props = props;
}
public void printConfig() {
System.out.println("URL: " + props.getUrl());
}
}
| 抽象層級 | 介面/類別 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|---|
| 底層資源 | Resource | 讀取任意格式檔案、流式處理 | 統一 classpath/file/URL 存取 | 需手動解析、無類型安全 |
| Properties 物件 | PropertiesFactoryBean | 舊專案遷移、簡單鍵值對 | 零程式碼、XML 宣告式 | 字串型別、無驗證、難重構 |
| Environment | Environment.getProperty() | 動態查詢、多來源合併 | 支援 Profile、PropertySource 優先序 | 仍為字串、散落在程式碼中 |
| 類型安全綁定 | @ConfigurationProperties | 所有新專案、生產環境 | IDE 支援、驗證、重構安全、文檔化 | 需預先定義類別 |
# application-dev.yml
jdbc.oracle.url: jdbc:oracle:thin:@dev-db:1521:orcl
# application-prod.yml
jdbc.oracle.url: jdbc:oracle:thin:@prod-db:1521:orcl
啟動時指定 --spring.profiles.active=prod,Spring 自動合併覆蓋。
@ConfigurationProperties(prefix = "jdbc.oracle")
@Validated
public class OracleJdbcProperties {
@NotBlank
private String url;
@Pattern(regexp = "^jdbc:oracle:thin:@.+")
private String url; // 進一步格式驗證
}
@RefreshScope
@ConfigurationProperties(prefix = "jdbc.oracle")
public class OracleJdbcProperties { ... }
配合 POST /actuator/refresh 實現不重啟更新配置。
@Value("classpath:${config.file.path:default-config.json}")
private Resource configResource;
resource.getFile() 拋出 FileNotFoundException:classpath 資源打包在 JAR 內時無法轉為 File,請改用 resource.getInputStream()。PropertiesFactoryBean 回傳的 Properties 若為 null:檢查 location 路徑是否正確、檔案是否在 classpath 根目錄。@PropertySource 與 @ConfigurationProperties 導致重複綁定:Boot 2.4+ 已整合,建議僅用 @ConfigurationProperties。Spring Cloud Vault、AWS Secrets Manager 或環境變數注入。Spring 讀取配置的演進路徑:
新專案請直接從第 3 種開始,享受類型安全、IDE 智慧提示、驗證與動態刷新的完整體驗。