Configuration类详解

1.configuration类简介

   Hadoop没有使用java.util.Properties管理配置文件,也没有使用Apache Jakarta Commons Configuration管理配置文件,而是使用了一套独有的配置文件管理系统,并提供自己的API,即使用org.apache.hadoop.conf.Configuration处理配置信息。这个类是作业的配置信息类,任何作用的配置信息必须通过Configuration传递,因为通过Configuration可以实现在多个mapper和多个reducer任务之间共享信息。

2.Hadoop配置文件的格式:

<?xml version="1.0"?> 
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> 
<property>
	<name>dfs.name.dir</name>
	<value>/home/hdfs/name</value>
	<description>.......</description> 
	<final>true</final> 
</property>
<property>
	<name>dfs.data.dir</name>
	<value>/home/hdfs/data</value>
</property>
</configuration> 

3.configuration类代码:

public class Configuration implements Iterable<Map.Entry<String,String>>,
                                      Writable {
  private static final Log LOG =
    LogFactory.getLog(Configuration.class);

  // 用来设置加载配置的模式。为true(默认值),在加载解析配置文件过程中,不输出日志信息。
  // quietmode只是一个方便开发人员调试的变量。
  private boolean quietmode = true;
  
  // resources用于存储整个XML文件,并不是存键值对,即表明资源列表
  private ArrayList<Object> resources = new ArrayList<Object>();

  // finalParameters的类型是Set<String>,用来保存所有在配置文件中已经被声明为final的键–值对的键
  private Set<String> finalParameters = new HashSet<String>();
  
  // 用于确定是否加载默认资源
  private boolean loadDefaults = true;
  
  private static final WeakHashMap<Configuration,Object> REGISTRY = 
    new WeakHashMap<Configuration,Object>();
  
  // 存放默认添加的XML文件资源
  private static final CopyOnWriteArrayList<String> defaultResources =
    new CopyOnWriteArrayList<String>();
  static{
    addDefaultResource("core-default.xml");
    addDefaultResource("core-site.xml");
  }
  
  // 配置文件解析后的键–值对,都存放在properties中,即用来存储加载出来的属性
  private Properties properties;	
  // 变量overlay用于记录通过set()方式改变的配置项。即出现在overlay中的键–值对是应用设置的,而不是通过对配置资源解析得到的。
  private Properties overlay;
  // 类加载器变量,可以通过它来加载指定类,也可以通过它加载相关的资源  
  private ClassLoader classLoader;
  {
    classLoader = Thread.currentThread().getContextClassLoader();
    if (classLoader == null) {
      classLoader = Configuration.class.getClassLoader();
    }
  }
  

  public Configuration() {
    this(true);
  }
  public Configuration(boolean loadDefaults) {
  }
  public Configuration(Configuration other) {
  }
  
  /************************************************/
  /**********向resources中添加XML资源**************/
  /************************************************/
  
   public static synchronized void addDefaultResource(String name) {
    if(!defaultResources.contains(name)) {
      defaultResources.add(name);
      for(Configuration conf : REGISTRY.keySet()) {
        if(conf.loadDefaults) {
          conf.reloadConfiguration();
        }
      }
    }
  }
  // 添加XML文件,在add完成XML文件的时候,不会去更新属性列表的,
  // 只有当有需要读取属性值的时候才会进行资源的加载。
  // 要注意的是,在addResource()的时候,会将给定的资源放到一个资源resources里面
  public void addResource(Path file) {
    addResourceObject(file);
  }
  // 添加资源,输入参数为XML文件名
  public void addResource(String name) {
    addResourceObject(name);
  }
  public void addResource(URL url) {
    addResourceObject(url);
  }
  public void addResource(InputStream in) {
    addResourceObject(in);
  }
  private synchronized void addResourceObject(Object resource) {
    resources.add(resource);    // XML添加到resources中
    reloadConfiguration();
  }
  // 重新加载配置
  public synchronized void reloadConfiguration() {
    properties = null;          		// 清除之前加载进来的全部属性
    finalParameters.clear();            // 因为可在属性里面标注final属性,这里将全部final属性清除掉。
  }
  

  /************************************************/
  /*********通过属性name获得其对应的值*************/
  /************************************************/
  
  // 返回属性name对应的值
  public String get(String name) {
    return substituteVars(getProps().getProperty(name));
  }
  public String getRaw(String name) {
    return getProps().getProperty(name);
  }
  // return property value, or defaultValue if the property doesn't exist.                    
  public String get(String name, String defaultValue) {
    return substituteVars(getProps().getProperty(name, defaultValue));
  }
  // return property value as an int, or defaultValue. 
  public int getInt(String name, int defaultValue) {
    String valueString = get(name);
    if (valueString == null)
      return defaultValue;
    try {
      String hexString = getHexDigits(valueString);
      if (hexString != null) {
        return Integer.parseInt(hexString, 16);
      }
      return Integer.parseInt(valueString);
    } catch (NumberFormatException e) {
      return defaultValue;
    }
  }
  public long getLong(String name, long defaultValue) {
  }
  public float getFloat(String name, float defaultValue) {
  }
  public boolean getBoolean(String name, boolean defaultValue) {
  }
  public Collection<String> getStringCollection(String name) {
    String valueString = get(name);
    return StringUtils.getStringCollection(valueString);
  }
  public String[] getStrings(String name) {
    String valueString = get(name);
    return StringUtils.getStrings(valueString);
  }
  public String[] getStrings(String name, String... defaultValue) {
  }

  /************************************************/
  /*********通过属性name设置其对应的值*************/
  /************************************************/
  
  // 设置属性name对应的值
  public void set(String name, String value) {
    getOverlay().setProperty(name, value);
    getProps().setProperty(name, value);
  }
  // 设置不存在的属性name对应的值
  public void setIfUnset(String name, String value) {
    if (get(name) == null) {
      set(name, value);
    }
  }
  // 通过int型设置属性name对应的值
  public void setInt(String name, int value) {
    set(name, Integer.toString(value));
  }
  public void setLong(String name, long value) {
    set(name, Long.toString(value));
  }
  public void setFloat(String name, float value) {
    set(name,Float.toString(value));
  }
  public void setBoolean(String name, boolean value) {
    set(name, Boolean.toString(value));
  }
  public void setBooleanIfUnset(String name, boolean value) {
    setIfUnset(name, Boolean.toString(value));
  }
  public void setStrings(String name, String... values) {
    set(name, StringUtils.arrayToString(values));
  }

  /************************************************************/
  /*********将resources中的XML资源加载到properties*************/
  /************************************************************/
 
  private synchronized Properties getProps() {
    if (properties == null) {
      properties = new Properties();
	  // 加载资源
      loadResources(properties, resources, quietmode);
      if (overlay!= null)
        properties.putAll(overlay);
    }
    return properties;
  }
  private void loadResources(Properties properties,
                             ArrayList resources,
                             boolean quiet) {
    if(loadDefaults) {
      for (String resource : defaultResources) {
        loadResource(properties, resource, quiet);
      }
      if(getResource("hadoop-site.xml")!=null) {
        loadResource(properties, "hadoop-site.xml", quiet);
      }
    }
    
    for (Object resource : resources) {
      loadResource(properties, resource, quiet);
    }
  }
  // 利用java DOM API对resource(XML)进行遍历,将全部的属性值加载到properties
  private void loadResource(Properties properties, Object name, boolean quiet) {
		// 部分代码省略
	  
		// Ignore this parameter if it has already been marked as 'final'
        if (attr != null && value != null) {
          if (!finalParameters.contains(attr)) {
			// 添加属性(键值对)
            properties.setProperty(attr, value);
            if (finalParameter)
              finalParameters.add(attr);
          }
  }

  /************************************************************/
  /*********其余方法********************************************/
  /************************************************************/

  /** 
   * Get the URL for the named resource.
   * @param name resource name.
   * @return the url for the named resource.
   */
  public URL getResource(String name) {
    return classLoader.getResource(name);
  }
  // Get an input stream attached to the configuration resource with the given name
  public InputStream getConfResourceAsInputStream(String name) {
  }
  public Reader getConfResourceAsReader(String name) {
  }

  public int size() {
    return getProps().size();
  }
  public void clear() {
    getProps().clear();
    getOverlay().clear();
  }

  /**
   * Get an Iterator to go through the list of String
   * key-value pairs in the configuration.
   * @return an iterator over the entries.
   */
  public Iterator<Map.Entry<String, String>> iterator() {
    // Get a copy of just the string to string pairs. After the old object
    // methods that allow non-strings to be put into configurations are removed,
    // we could replace properties with a Map<String,String> and get rid of this
    // code.
    Map<String,String> result = new HashMap<String,String>();
    for(Map.Entry<Object,Object> item: getProps().entrySet()) {
      if (item.getKey() instanceof String && 
          item.getValue() instanceof String) {
        result.put((String) item.getKey(), (String) item.getValue());
      }
    }
    return result.entrySet().iterator();
  }
  
  
 
  public synchronized void setQuietMode(boolean quietmode) {
    this.quietmode = quietmode;
  }

  /** For debugging.  List non-default properties to the terminal and exit. */
  public static void main(String[] args) throws Exception {
  }


  public void readFields(DataInput in) throws IOException {
    clear();
    int size = WritableUtils.readVInt(in);
    for(int i=0; i < size; ++i) {
      set(org.apache.hadoop.io.Text.readString(in), 
          org.apache.hadoop.io.Text.readString(in));
    }
  }

  public void write(DataOutput out) throws IOException {
    Properties props = getProps();
    WritableUtils.writeVInt(out, props.size());
    for(Map.Entry<Object, Object> item: props.entrySet()) {
      org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());
      org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());
    }
  }
}

   说明:Configuration实现了Iterable和Writable两个接口,其中实现Iterable是为了迭代,迭代出Configuration对象加载到内存中的所有name-value键值对。实现Writable是为了实现hadoop框架要求的序列化,可以将内存中的name-value序列化到硬盘,关于这两个接口的具体实现的话,我想不用再多说了,应该想的明白。

4.Configuration使用

   合并资源指将多个配置文件合并,产生一个配置。如果有两个配置文件,也就是两个资源,如core-default.xml和core-site.xml,通过Configuration类的loadResources()方法,把它们合并成一个配置。代码如下:

Configuration conf = new Configuration();  
conf.addResource("core-default.xml");  
conf.addResource("core-site.xml"); 


   如果这两个配置资源都包含了相同的配置项,而且前一个资源的配置项没有标记为final,那么,后面的配置将覆盖前面的配置。

   Hadoop配置系统还有一个很重要的功能,就是属性扩展。如配置项dfs.name.dir的值是${hadoop.tmp.dir}/dfs/name,其中,${hadoop.tmp.dir}会使用Configuration中的相应属性值进行扩展。

   使用Configuration类的一般过程是:构造Configuration对象,并通过类的addResource()方法添加需要加载的资源;然后就可以使用get*方法和set*方法访问/设置配置项,资源会在第一次使用的时候自动加载到对象中。


http://f.dataguru.cn/thread-258563-1-1.html

http://www.cnblogs.com/shaoyexin/archive/2013/03/23/2977235.html

http://www.hackbase.com/tech/2014-12-12/70073.html







  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值