springboot自定义加载配置文件

实现

springboot提供了注解@PropertySource来实现加载配置文件。 一个普通的注解配置,也可注解在其他@Configuration类上

1
2
3
4
@SpringBootApplication
@PropertySource(factory = YamlPropertySourceFactory.class, value = "classpath:application.yml")
public class Application {
}

PropertySourcePropertySourceFactory的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

package org.springframework.context.annotation;

public @interface PropertySource {
String name() default "";
String[] value();
boolean ignoreResourceNotFound() default false;
String encoding() default "";
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;

}

public interface PropertySourceFactory {
PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException;
}

PropertySourcefactory来表示使用何种PropertySourceFactory来实现加载过程,value指向的文件会被spring加载为EncodedResource实例以供PropertySourceFactory使用

value的值需要为有效资源,若我们需要加载绝对路径的资源文件,我们无视value的资源,仅加载自己所需要加载的配置文件。 首先我们了解下如何加载yaml配置

custom.yml配置文件,路径为/Users/li/java/workspace/branches/src/main/resources/custom.yml

1
foo: 1

我们可以使用FileSystemResource加载文件资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.leaderli.branches.utils;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.support.EncodedResource;

import java.io.File;
import java.util.Properties;

public class ConfigUtil {
public static Properties loadYamlIntoProperties(String yml) {

EncodedResource resource = new EncodedResource(new FileSystemResource(new File(yml)));
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}

测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.leaderli.branches.config;

import com.leaderli.branches.utils.ConfigUtil;
import org.junit.jupiter.api.Test;

import java.util.Properties;

class YamlPropertySourceFactoryTest {
@Test
public void test() {
String yml = "/Users/li/java/workspace/branches/src/main/resources/custom.yml";
Properties properties = ConfigUtil.loadYamlIntoProperties(yml);
assert (int)properties.get("foo") == 1;
}
}

接下来只需要实现PropertySourceFactory接口即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.leaderli.branches.config;

import com.leaderli.branches.utils.ConfigUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

import java.io.IOException;
import java.util.Properties;

public class YamlPropertySourceFactory implements PropertySourceFactory {
private static final Log LOGGER = LogFactory.getLog(YamlPropertySourceFactory.class);


@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = ConfigUtil.loadYamlIntoProperties("/Users/li/java/workspace/branches/src/main/resources/custom.yml");
String sourceName = name != null ? name : resource.getResource().getFilename();
LOGGER.debug("resouce:" + resource);
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}

}