在Hadoop 2.6.0中,Configuration类的作用主要提供配置参数的相关信息。其中定义了一个内部类Resource用来存放相应的单个xml配置文件的可达信息(包括String、Path、URL、InputStram、Properties、Element等),并从xml文件中解析出来的键值对存放在Properties对象中。
介绍
1.资源
Configuration中配置信息由相关的xml配置文件指定,而xml配置文件中由一系列键值对组成,因此Configuration的主要功能即使找到这些xml配置文件,并且加载至类中。此时涉及两个问题,即如何加载和如何存放。首先Configuration内部定义了一个Resource类来存放xml配置文件的可达信息,包括String、Path、URL、InputStram、Properties、Element等,通过这些可达信息,就能找到相应的xml文件的具体位置,接下来便是通过Java进行xml解析,从而得到xml中的键值对的信息。在得到键值对后就是如何存放的问题了,在Configuration内部有一个Properties类的字段,分别将这些键值对存放到该对象当中即可。
当Configuration类被加载时,会默认初始化core-default.xml和core-site.xml这两个配置文件。
2.Final参数
在Configuration类中的参数可以被声明为Final类型,其中Final类型类似于Java中的final的用处,即不允许用户修改被声明为final类型的键对应的值。声明的方法就是在xml文件中在相应的配置参数中添加 < final > true< /final > 标签即可。
初始化过程
初始化过程包括类初始化过程和实例初始化过程。首先当Java虚拟机加载该类时会进行类初始化,而之后当创建该类具体的对象时会进行实例初始化。Configuration中的初始化过程中,只会将相应的xml文件可达路径保存在Resource对象中,并不会马上进行xml的解析。只有当调用该对象的get*方法时,若检测到Properties字段为空时,才会进行xml解析,并把相应的键值对存放到Properties对象中去。
类初始化过程
static{
//print deprecation warning if hadoop-site.xml is found in classpath
ClassLoader cL = Thread.currentThread().getContextClassLoader();
if (cL == null) {
cL = Configuration.class.getClassLoader();
}
if(cL.getResource("hadoop-site.xml")!=null) {
LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
"Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
+ "mapred-site.xml and hdfs-site.xml to override properties of " +
"core-default.xml, mapred-default.xml and hdfs-default.xml " +
"respectively");
}
addDefaultResource("core-default.xml");
addDefaultResource("core-site.xml");
}
这是一个静态初始化块,当Java虚拟机加载该类时,首先会调用该初始化块。从初始化块中可以看到,一开始会取得类加载器ClassLoader,通过这个类加载器寻找是否存在hadoop-site.xml,若存在就会发出一条警告,因为这个配置文件是老版本的文件,而现在的版本已不再这样命名。接着会调用静态方法addDefaultResource加载core-default.xml和core-site.xml(并不会对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();
}
}
}
}
上面addDefaultResource静态方法中,包含两个静态类变量:defaultResources(属于CopyOnWriteArrayList<String>
类)和REGISTRY(属于WeakHashMap<Configuration,Object>
类)。布尔变量loadDefaults用于确定是否加载默认资源。该方法作用即是判断defaultResources中是否含有name这个值,若没有就添加进去。REGISTRY存放的为具体的已经实例化的Configuration对象,在后面实例初始化时创建的对象会放入REGISTRY中。后面半部分代码表示当调用addDefaultResource这个静态方法时,并且之前创建的Configuration对象的loadDefaults字段为true时,会将properties(存放具体键值对)赋值为null,并且将finalParameters内的数据清空,finalParameters是一个HashSet类,用来存放声明了final的参数。
实例初始化过程
private ClassLoader classLoader;
{
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = Configuration.class.getClassLoader();
}
}
上面方法意思很直白,就是获得一个类加载器classLoader,并赋给成员变量。
public Configuration() {
this(true);
}
public Configuration(boolean loadDefaults) {
this.loadDefaults = loadDefaults;
updatingResource = new HashMap<String, String[]>();
synchronized(Configuration.class) {
REGISTRY.put(this, null);
}
}
上面代码为Configuration的构造器,十分的简单,可以注意到REGISTRY.put(this, null)
这条语句,当每次实例化一个对象时,都会将自己注册到REGISTRY中去。
到此为止,所有的初始化过程就结束了。但是可以看到当中并没有任何解析xml文件中键值对的相应的语句。这是因为在初始化时,只是简单的将xml的文件名保存下来,只有当调用该对象中的get*的语句时,才会进行xml的解析,并将解析后的值保存到properties当中去。