@PropertySource
註解是Spring用於載入配置檔案,預設支援.properties
與.xml
兩種配置檔案。@PropertySource
屬性如下:
- name:預設為空,不指定
Spring
自動生成 - value:配置檔案
- ignoreResourceNotFound:沒有找到配置檔案是否忽略,預設
false
,4.0版本加入 - encoding:配置檔案編碼格式,預設
UTF-8
4.3版本才加入 - factory:配置檔案解析工廠,預設:
PropertySourceFactory.class
4.3版本才加入,如果是之前的版本就需要手動注入配置檔案解析Bean
接下來就使用@PropertySource
來載入.properties
與.xml
配置檔案。這裡模擬連線MySQL
資料庫。
首先新增依賴:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
準備屬性配置檔案jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306
jdbc.userName=root
jdbc.password=xiaohu
建立屬性實體類來載入配置檔案JdbcProperties
@Data
@Repository
@PropertySource(value = "classpath:jdbc.properties")
public class JdbcProperties {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.userName}")
private String userName;
@Value("${jdbc.password}")
private String password;
}
建立JDBC配置類JdbcConfig
@Component
public class JdbcConfig {
@Bean
public DataSource dataSource(JdbcProperties jdbcProperties){
System.out.println("列印獲取到的配置資訊:"+jdbcProperties);
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcProperties.getDriver());
dataSource.setUrl(jdbcProperties.getUrl());
dataSource.setUsername(jdbcProperties.getUserName());
dataSource.setPassword(jdbcProperties.getPassword());
return dataSource;
}
}
建立Spring
配置類SpringConfiguration
@Configuration
public class SpringConfiguration {
}
建立測試類測試讀取配置檔案
public class PropertySourceTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("config");
DataSource dataSource = context.getBean("dataSource",DataSource.class);
System.out.println(dataSource);
}
}
檢視輸出結果:
列印獲取到的配置資訊:JdbcProperties(driver=com.mysql.cj.jdbc.Driver, url=jdbc:mysql://127.0.0.1:3306, userName=root, password=xiaohu)
org.springframework.jdbc.datasource.DriverManagerDataSource@58695725
從結果可以看出,我們的properties
中的配置已經成功讀取到,並且DataSource
也從Spring
容器中獲取到。上面介紹註解的屬性時,factory
是4.3版本才加入的,那麼如果4.3版本之前要解析配置檔案又應該怎麼處理呢?,這個時候就需要手動將解析配置檔案的Bean注入到Spring
容器中了,用法很簡單,在SpringConfiguration
類中新增如下程式碼即可:
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
具體測試結果,就自行測試了。上面例子介紹了properties
的使用,下面我們將配置檔案換成xml
檔案。配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="jdbc.driver">com.mysql.cj.jdbc.Driver</entry>
<entry key="jdbc.url">jdbc:mysql://127.0.0.1:3306/test</entry>
<entry key="jdbc.userName">root</entry>
<entry key="jdbc.password">xiaohu</entry>
</properties>
然後將JdbcProperties
類上的註解的配置檔案換成xml
檔案。
@PropertySource(value = "classpath:jdbc.properties")
其他不用調整,執行測試類,輸出的結果一樣。因為上面介紹到@PropertySource
預設支援properties
與xml
的配置檔案。我們可以檢視PropertySourceFactory
的預設實現DefaultPropertySourceFactory
原始碼
public class DefaultPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}
}
然後進入ResourcePropertySource
類,原始碼這裡使用了一個三元運算子,如果name
為空,就使用預設Spring
預設生成的name
。
public ResourcePropertySource(String name, EncodedResource resource) throws IOException {
super(name, PropertiesLoaderUtils.loadProperties(resource));
this.resourceName = getNameForResource(resource.getResource());
}
public ResourcePropertySource(EncodedResource resource) throws IOException {
super(getNameForResource(resource.getResource()), PropertiesLoaderUtils.loadProperties(resource));
this.resourceName = null;
}
這裡可以看到呼叫了PropertiesLoaderUtils.loadProperties
方法,進入到原始碼
public static Properties loadProperties(EncodedResource resource) throws IOException {
Properties props = new Properties();
fillProperties(props, resource);
return props;
}
會呼叫fillProperties
的方法,一直跟到呼叫最低的fillProperties
方法。
static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
throws IOException {
InputStream stream = null;
Reader reader = null;
try {
String filename = resource.getResource().getFilename();
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
stream = resource.getInputStream();
persister.loadFromXml(props, stream);
}
else if (resource.requiresReader()) {
reader = resource.getReader();
persister.load(props, reader);
}
else {
stream = resource.getInputStream();
persister.load(props, stream);
}
}
finally {
if (stream != null) {
stream.close();
}
if (reader != null) {
reader.close();
}
}
}
第一個if
判斷檔案字尾是否是xml
結尾,常量XML_FILE_EXTENSION
如下:
private static final String XML_FILE_EXTENSION = ".xml";
除了支援properties
與xml
的配置檔案方式,也支援yml
配置檔案的方式,不過需要自定義解析工廠,下面來實現怎麼解析yml
配置檔案。引入可以解析yml
檔案的第三方庫
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
</dependency>
建立yml
解析工廠YamlPropertySourceFactory
實現PropertySourceFactory
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
factoryBean.setResources(resource.getResource());
Properties properties = factoryBean.getObject();
return name != null ? new PropertiesPropertySource(name, properties) : new PropertiesPropertySource(resource.getResource().getFilename(), properties);
}
}
然後將JdbcProperties
類的@PropertySource
換成如下寫法:
@PropertySource(value = "classpath:jdbc.yml",factory = YamlPropertySourceFactory.class)
執行測試類,輸出結果與上面結果一樣
列印獲取到的配置資訊:JdbcProperties(driver=com.mysql.cj.jdbc.Driver, url=jdbc:mysql://127.0.0.1:3306, userName=root, password=xiaohu)
org.springframework.jdbc.datasource.DriverManagerDataSource@58695725
證明我們自定義的解析yml
配置檔案就成功了。