在日常项目中通常会使用Properties文件来配置项目中的一些配置化属性,但是由于Properties是写在项目中的导致每当更改配置时都需要更新代码重新发布,另一方面类似一些密码,密匙一类的配置写在代码中也十分的不安全,所以我们可以通过继承PropertyPlaceholderConfigurer来实现一些结构化配置的自定义。
配置管理中心如何实现
简单实现通过数据库保存配置数据,同时加入缓存,条件充足可以多加两层缓存保证只要不是所有层级都挂掉就可以访问,一切从简此处直说原理,我们可以直接将查询逻辑写在我们的项目中,先从缓存中查询,查询失败从二级缓存或数据库查询。配置数据的管理可以开发一个简单的管理平台只要实现数据库更删改查和缓存同步就可以了
PropertyPlaceholderConfigurer的工作原理
通常我们在项目中的配置采用下述的方式进行配置,相关的结构化配置都写在Properties文件中通过${name}的方式来获取配置属性。
<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:/conf/**/dubbo.properties</value>
<value>classpath*:/conf/**/image.properties</value>
<value>classpath*:/conf/**/db.properties</value>
</list>
</property>
</bean>
spring只会在服务启动时调用PropertyPlaceholderConfigurer类加载一次配置信息,只要服务没有重启系统中使用的将一直是服务启动时加载的配置。
重写配置加载流程
知道了这个原理 我们就可通过继承PropertyPlaceholderConfigurer类通过重写其内部的方法来在这个过程中做一些我们想要的操作。
我们最终选择重写PropertyPlaceholderConfigurer实现的PropertiesLoaderSupport抽象类的mergeProperties()方法,该方法是spring在读取加载完全部的properties文件后将属性整合入Properties类中的方法,代码如下:
/**
* Created by ljs on 2018/7/18.
* 加载配置中心配置
*/
public class MyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
//设置一些我们需要的入参
private String pram1;
private String pram2;
/***
* 重写mergeProperties方法加载配置中心配置
* @return
* @throws IOException
*/
@Override
protected Properties mergeProperties() throws IOException {
//调用父类的mergeProperties方法实现对项目中原有使用properties文件的方式进行兼容
Properties props = super.mergeProperties();
//此时props内就是我们在properties文件内的配置了,
//由于此时完整的配置加载流程并没有执行完成,所以如果需要在此时使用配置文件内的配置的话可以通过props.get(name)的方式获取数据,
/***获取结构化配置数据存入list中*/
List<Map> list = 调用配置查询方法;
//遍历查询出的配置将其塞入props中
for (Map<String,String> map:list) {
for(Map.Entry entry : map.entrySet()){
props.setProperty(entry.getKey().toString(),entry.getValue().toString());
}
}
//最终返回的Properties中就加入了我们从配置管理中心查询到的配置了
return props;
}
public String getPram1() {
return pram1;
}
public void setPram1(String pram1) {
this.pram1 = pram1;
}
public String getPram2() {
return pram2;
}
public void setPram2(String pram2) {
this.pram2 = pram2;
}
}
spring配置
将class配置为我们自定义的MyPropertyPlaceholderConfigurer类
<bean id="propertyConfigurer"class=“com.common.MyPropertyPlaceholderConfigurer”>
<property name="locations">
<!--j兼容properties配置-->
<list>
<value>classpath*:/conf/**/dubbo.properties</value>
<value>classpath*:/conf/**/image.properties</value>
<value>classpath*:/conf/**/db.properties</value>
</list>
</property>
<!--传入一些我们可能需要的自定义参数-->
<property name="pram1" value="pram1l"/>
<property name="pram2" value="pram1"/>
</bean>
好了这样我们就可以在项目中使用我们自定义的配置了,当然通常我们还会在配置中增加一些加密加密的操作,大家可以视情况添加,此处只是简单实现说一下原理。
总结
使用静态代理的思想实现 通过我们新的代理对象在mergeProperties方法执行后进行一些自定义炒作。