以上分析的代码都是前期的操作,那么比较关键的set/get这类和属性直接相关的方法怎么实现的,所以这个时候,必须要先了解Hadoop中的配置文件是怎样的格式存在于文件中的。比如HDFS的配置文件hdfs-site.xml;
dfs.name.dir
/var/local/hadoop/hdfs/name
Determines where on the local filesystem the DFS name node should store the name table. If this is a comma-delimited list of directories then the name table is replicated in all of the directories, for redundancy.
true
dfs.data.dir
/var/local/hadoop/hdfs/data
Determines where on the local filesystem an DFS data node should store its blocks. If this is a comma-delimited list of directories, then data will be stored in all named directories, typically on different devices. Directories that do not exist are ignored.
true
.......
节点层级的关系不是很复杂,关键在每个Property节点保留name名字,value值,des对于此属性的描述,final标签用于判断此属性能不能被改变,为true代表无法变更,类似于java语言里的final关键字。了解完配置文件的结构之后,就可以继续往下看了,比如我要设置1个属性,set的一个小小的方法如下:
/** * Set the后面的setProperty就是Property的设置方法,jdk的API,所以关键就是前面获取getProps的方法,如何把文件中的属性加载到Property的变量中的。valueof thenameproperty. * * @param name property name. * @param value property value. * 根据name设置属性值,属性键值对保存在property中 */ public void set(String name, String value) { getOverlay().setProperty(name, value); getProps().setProperty(name, value); }
/**
* 加载的时候采用了延时加载的策略
* @return
*/
private synchronized Properties getProps() {
if (properties == null) {
properties = new Properties();
//从资源中再次获取属性相关的数据
loadResources(properties, resources, quietmode);
if (overlay!= null) {
properties.putAll(overlay);
if (storeResource) {
for (Map.Entry
看了上面为NULL的判断,也许你就知道为什么刚刚的重新加载操作那么简单,就执行了clear操作就完了,就是等着后面真正要获取这个Property的时候在加载的,就是所谓的延时加载策略,类似于单例模式中的懒汉式模型。所以loadResources又是此实现的关键:
private void loadResource(Properties properties, Object name, boolean quiet) {
try {
//工厂模式获取解析xml文件对象,这里用的是doc解析方式
DocumentBuilderFactory docBuilderFactory
= DocumentBuilderFactory.newInstance();
//ignore all comments inside the xml file
docBuilderFactory.setIgnoringComments(true);
//allow includes in the xml file
docBuilderFactory.setNamespaceAware(true);
try {
docBuilderFactory.setXIncludeAware(true);
} catch (UnsupportedOperationException e) {
LOG.error("Failed to set setXIncludeAware(true) for parser "
+ docBuilderFactory
+ ":" + e,
e);
}
DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
.....
if (root == null) {
//获取xml中的节点进行获取,这里先获取了根节点
root = doc.getDocumentElement();
}
if (!"configuration".equals(root.getTagName()))
LOG.fatal("bad conf file: top-level element not
");
NodeList props = root.getChildNodes();
for (int i = 0; i < props.getLength(); i++) {
Node propNode = props.item(i);
if (!(propNode instanceof Element))
continue;
Element prop = (Element)propNode;
if ("configuration".equals(prop.getTagName())) {
//如果子节点是configuration,则再次递归调用loadResource()方法
loadResource(properties, prop, quiet);
continue;
}
if (!"property".equals(prop.getTagName()))
LOG.warn("bad conf file: element not
"); NodeList fields = prop.getChildNodes(); String attr = null; String value = null; boolean finalParameter = false; for (int j = 0; j < fields.getLength(); j++) { Node fieldNode = fields.item(j); if (!(fieldNode instanceof Element)) continue; //属性节点分3种判断,name,value,final Element field = (Element)fieldNode; if ("name".equals(field.getTagName()) && field.hasChildNodes()) attr = ((Text)field.getFirstChild()).getData().trim(); if ("value".equals(field.getTagName()) && field.hasChildNodes()) value = ((Text)field.getFirstChild()).getData(); if ("final".equals(field.getTagName()) && field.hasChildNodes()) //final参数需额外添加到finalParameters参数的集合中 finalParameter = "true".equals(((Text)field.getFirstChild()).getData()); } // Ignore this parameter if it has already been marked as 'final' if (attr != null) { if (value != null) { if (!finalParameters.contains(attr)) { //在这步把上面去的值放入properties属性中 properties.setProperty(attr, value); if (storeResource) { updatingResource.put(attr, name.toString()); } } else if (!value.equals(properties.getProperty(attr))) { LOG.warn(name+":a attempt to override final parameter: "+attr +"; Ignoring."); } } if (finalParameter) { finalParameters.add(attr); } } }
和上面我们看的实际配置文件一对照,就不难理解了,就是简单的doc解析xml文件,这里不过多了一些处理,比如final的参数要额外再做一下操作。加载完成之后,属性信息就被放到了Property中了,就达成了目标了。
下面我们说说get的属性获取操作,同样有别样的设计,他可不仅仅是getProps().get(name)这样的操作