天天看點

Spring的@PropertySource注解使用

@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

配置檔案就成功了。