• configuration类详解


    hadoop中,组件配置是由Hadoop的Configuration的一个实例实现。(在源码包的org.apache.hadoop.conf中可以找到)先上个类图:这只是部分的,Configuraation涉及的方法很多,不一一例举了。

    configuration

    在这里面我们看到的是整个hadoop的核心包的conf package里面涉及到全部类和接口。

    在书中,我们可以看到一个XML文档以及一个利用configuration实例来读取XML文档的程序。这里搬过来,方便下面的学习分析。

    复制代码
    <?xml version="1.0"?>
    <configuration>
      <property>
        <name>color</name>
        <value>yellow</value>
        <description>Color</description>
      </property>
      
      <property>
        <name>size</name>
        <value>10</value>
        <description>Size</description>
      </property>
      
      <property>
        <name>weight</name>
        <value>heavy</value>
        <final>true</final>
        <description>Weight</description>
      </property>
      
      <property>
        <name>size-weight</name>
        <value>${size},${weight}</value>
        <description>Size and weight</description>
      </property>
    </configuration>
    复制代码
    java实例代码如下:
        Configuration conf = new Configuration();
        conf.addResource("configuration-1.xml");
        assertThat(conf.get("color"), is("yellow"));
        assertThat(conf.getInt("size", 0), is(10));
        assertThat(conf.get("breadth", "wide"), is("wide"));

    在这里我们主要首先关注一个get(String name)方法.

    public String get(String name) {
        return substituteVars(getProps().getProperty(name));
      }

    首先应该从addResource()说起,如conf.addResource("configuration-1.xml"),这里实现了类似懒加载的方法来实现资源的读取,也就是说在add完成XML文件的时候,是不会去更新属性列表的,只有当有需要读取属性值的时候才会进行资源的加载。要注意的是,在addResource()的时候,会将给定的资源放到一个资源private ArrayList 里面,然后会调用reloadConfiguration方法:

    public synchronized void reloadConfiguration() {
        properties = null;                            // 清除之前加载进来的全部属性
        finalParameters.clear();                      // 因为可以在属性里面标注final属性,所以在这里可以将全部的final属性全部也清除掉。
      }

    读取属性的时候,就会先调用getProps()方法,这个方法里面调用了Configuration类里面的一个核心方法,loadResources():

    复制代码
    private void loadResources(Properties properties, ArrayList resources, boolean quiet) {
        //三个参数,properties用来存储加载出来的属性,resources表明资源列表, quiet表示静默模式,默认不会存储新加进来的资源文件,只会进行临时加载。
        if(loadDefaults) {
          for (String resource : defaultResources) {
            loadResource(properties, resource, quiet);
          }
        
          //support the hadoop-site.xml as a deprecated case
          if(getResource("hadoop-site.xml")!=null) {
            loadResource(properties, "hadoop-site.xml", quiet);
          }
        }
        
        for (Object resource : resources) {
          loadResource(properties, resource, quiet);
        }
      }
    复制代码

    这里提供了三张资源加载的方式,但是最后是由loadResource(properties, resource, quiet)这一方法来实现的。这里主要的实现是利用java DOM API 对所有的resource进行遍历,将全部的属性值加载到这里面来。初始化代码如下:

    复制代码
         DocumentBuilderFactory docBuilderFactory 
            = DocumentBuilderFactory.newInstance();
          //实例化一个工厂类
          docBuilderFactory.setIgnoringComments(true);
    
          //忽略开头的命名空间等信息
          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();
          Document doc = null;
          Element root = null;
    复制代码

    因为有string url inputstream三种格式的参数传进来,前两种都会转成URL的形式送到builder.parse()来解析。

    由上面大家也看到了,采用了DOM的解析方式。熟悉XML的人都知道,还有一种比较流行的解析方式,SAX解析。在这里,相对的XML文档不会太多,所以解析的效果也不会有明显的差异,都是可行的。但是DOM的解析方式更为的直观、直接。

    部分的for循环当中的代码:

    复制代码
            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;
              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())
                finalParameter = "true".equals(((Text)field.getFirstChild()).getData());
            }
    复制代码

    最后经过

    properties.setProperty(attr, value);

    放入结合当中,这样就产生了get()方法调用substituteVars方法的getPros()的方法。

    在学习上述的代码的时候,我慢慢体会到了,java私有方法和公有方法的一些使用的要点。那就是在使用私有方法的时候,应该尽可能的降低其对于全局变量的依赖性,可以在调用私有方法前尽可能的去掉一些不要的逻辑,让私有方法好好的工作。像configuration这个类,从addResource到loadResource,都是极尽可能的消除方法后端的一些影响因素,将更多的逻辑分担出来,使得代码的阅读更加的简单明了,这是一个程序员应该有的品质吧。

    最后要说一下,这里面还有一个用于属性导出的函数,也是一个比较值得学习的方法,这里就把代码贴出来。

    复制代码
    public static void dumpConfiguration(Configuration conf, 
          Writer out) throws IOException {
        Configuration config = new Configuration(conf,true);
        config.reloadConfiguration();
        JsonFactory dumpFactory = new JsonFactory();
        JsonGenerator dumpGenerator = dumpFactory.createJsonGenerator(out);
        dumpGenerator.writeStartObject();
        dumpGenerator.writeFieldName("properties");
        dumpGenerator.writeStartArray();
        dumpGenerator.flush();
        for (Map.Entry<Object,Object> item: config.getProps().entrySet()) {
          dumpGenerator.writeStartObject();
          dumpGenerator.writeStringField("key", (String) item.getKey());
          dumpGenerator.writeStringField("value", 
              config.get((String) item.getKey()));
          dumpGenerator.writeBooleanField("isFinal",
              config.finalParameters.contains(item.getKey()));
          dumpGenerator.writeStringField("resource",
              config.updatingResource.get(item.getKey()));
          dumpGenerator.writeEndObject();
        }
        dumpGenerator.writeEndArray();
        dumpGenerator.writeEndObject();
        dumpGenerator.flush();
      }
  • 相关阅读:
    SDN第四次上机作业
    SDN第四次作业
    SDN第三次上机作业
    SDN第三次作业
    SDN第二次上机作业
    SDN第二次作业
    个人作业——软件产品案例分析(待更)
    软工 实验三 需求分析(沈樟伟组)
    个人博客二:需求分析
    微软小娜APP的案例分析
  • 原文地址:https://www.cnblogs.com/baoendemao/p/3804754.html
Copyright © 2020-2023  润新知