1.使用spring中的知识点
A.Spring从3.1版本开始增加了ConfigurableEnvironment和PropertySource:
- ConfigurableEnvironment
Spring的ApplicationContext会包含一个Environment(实现ConfigurableEnvironment接口)
ConfigurableEnvironment自身包含了很多个PropertySource
- PropertySource
属性源
可以理解为很多个Key - Value的属性配置
需要注意的是,PropertySource之间是有优先级顺序的,如果有一个Key在多个property source中都存在,那么在前面的property source优先。
B.Spring中的BeanFactoryPostProcessor
在标准初始化之后修改应用程序上下文的内部bean工厂。所有的bean定义都将被加载,但是没有bean被实例化。这允许覆盖或添加属性,甚至是对迫切初始化的bean。
也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,所以在此过成中添加上自定义的PropertySource。
C.Spring中的EnvironmentAware,用于获取 ConfigurableEnvironment
此外,不得不提一下Aware
接口,它其实是一个空接口,里面不包含任何方法。它表示已感知的意思,通过这类接口可以获取指定对象,比如:
- 通过BeanFactoryAware获取BeanFactory
- 通过ApplicationContextAware获取ApplicationContext
- 通过BeanNameAware获取BeanName等
2.主要实现代码如下:
1.自定义类PropertySourcesProcessor,作用:实例化之前添加自定义的PropertySource
@Component public class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware { private ConfigurableEnvironment environment; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { if (! this .environment.getPropertySources().contains( "test" )) { //PropertySource<T>中的 泛型具体类型,在该类中,获取外部参数 ReadSettings readSettings = new ReadSettings(); //实例化自定义的 PropertySource ConfigPropertySource propertySource = new ConfigPropertySource( "test" ,readSettings); //把PropertySource添加到spring environment中 this .environment.getPropertySources().addFirst(propertySource); } } @Override public void setEnvironment(Environment environment) { this .environment = (ConfigurableEnvironment)environment; } } |
2.自定义类ConfigPropertySource,继承EnumerablePropertySource类,作用:重写getProperty方法,读取外部配置
public class ConfigPropertySource extends EnumerablePropertySource<ReadSettings> { public ConfigPropertySource(String name, ReadSettings source) { super (name, source); } @Override public String[] getPropertyNames() { Set<String> keys = this .source.getKeys(); return keys.toArray( new String[keys.size()]); } //重写 getProperty 方法,value值从 ReadSettings 中获取 @Override public Object getProperty(String s) { return this .source.readValue(s); } } |
3.自定义类ReadSettings,作用:读取外部资源功能类
public class ReadSettings { private Properties pro = new Properties(); public String readValue(String name){ try { //这里也可以通过HTTP请求远程读取配置文件 pro = new Properties(); InputStream in = new BufferedInputStream( new FileInputStream( "C:\\Users\\Administrator\\Desktop\\222.properties" )); pro.load(in); String property = pro.getProperty(name); return property; } catch (IOException e) { e.printStackTrace(); } return System.currentTimeMillis()+ "" ; } public Set<String> getKeys(){ Set<String> keys = new HashSet<>(); Iterator i$ = pro.entrySet().iterator(); while (i$.hasNext()) { Map.Entry<Object, Object> e = (Map.Entry)i$.next(); keys.add(e.getKey().toString()); } return keys; } } |
在使用配置文件时,直接使用@Value 注解即可。
参考apollo配置中心,客户端启动读取远程配置文件方法
https://ctripcorp.github.io/apollo/#/zh/design/apollo-design?id=_31-%e5%92%8cspring%e9%9b%86%e6%88%90%e7%9a%84%e5%8e%9f%e7%90%86