InputFormat默认实现类——TextInputFormat源码解析
以MapReduce程序中的Diver类调用的waitForCompletion方法为切入点,进行源码的剖析,这里以JDK8
为例。
Diver.class
:
// 按住ctrl键并点击waitForCompletion()进入Job.class类
job.waitForCompletion(true);
Job.class
:
方法1:waitForCompletion()
/*
主要关注waitForCompletion()方法中调用的submit()方法,该方法用来提交job
然后继续跟进submit(),仍然是在Job.class
*/
this.submit();
方法2:submit()
/*
关注submit()方法中调用的submitJobInternal()方法,进行内部提交。
继续跟进该方法进入JobSubmitter.class类中。
*/
return submitter.submitJobInternal(Job.this, Job.this.cluster);
JobSubmitter.class
:
方法3:submitJobInternal()
/*
上边大部分代码暂时不用看,直接找到调用writeSplits()方法的代码。
该句代码的作用是计算切片,生成切片规划文件。
接着继续跟进writeSplits()方法,仍然是在JobSubmitter.class中。
*/
int maps = this.writeSplits(job, submitJobDir);
方法4:writeSplits()
//在writeSplits()方法中调用了writeNewSplits()方法,进行切片
//然后继续跟进writeNewSplits()方法,仍然实在JobSubmitter.class中。
maps = this.writeNewSplits(job, jobSubmitDir);
方法5:writeNewSplits()
/*
在该方法中终于可以看到了InputFormat抽象类获取实例,参数传入一个实现类。
再通过反射机制获取类的实例化,从而达到实例化的过程。
因此只需要确定参数中getInputFormatClass()方法返回的具体是谁就可以确定具体实现类。
继续跟进getInputFormatClass()方法,进入JobContext.class。
*/
InputFormat<?, ?> input = (InputFormat)ReflectionUtils.newInstance(job.getInputFormatClass(), conf);
JobContext.class
/*
JobContext.class中的getInputFormatClass()是一个抽象类方法,其具体的实现类包括五个:
ChainMapContextImpl.class
ChainReduceContextImpl.class
Context in WrappedMapper.class
Context in WrappedReducer.class
JobContextImpl.class
但是通过一个一个跟进,只有JobContextImpl.class类中的重写方法具有真实业务逻辑。
*/
Class<? extends InputFormat<?, ?>> getInputFormatClass() throws ClassNotFoundException;
JobContextImpl.class
/*
首先会去默认配置文件中查找标签"mapreduce.job.inputformat.class"的对应值
但是mapred-default.xml默认配置文件中没有配置,因此会返回显示声明的参数TextInputFormat.class
*/
public Class<? extends InputFormat<?, ?>> getInputFormatClass() throws ClassNotFoundException {
return this.conf.getClass("mapreduce.job.inputformat.class", TextInputFormat.class);
}