1. 开始执行一个Step
单线程的Step一般使用的实现类是TaskletStep
Step的执行从 Step抽象类 AbstractStep
中的execute方法开始
这个方法完成了一下几个工作
1.1 Step执行前的准备工作
- 更新StepExecution 也就是Step执行信息到存储库
- 注册StepExecution
- 触发Step监听器的beforeStep方法
- 执行steam接口的open方法
stepExecution.setStartTime(new Date());
stepExecution.setStatus(BatchStatus.STARTED);
getJobRepository().update(stepExecution);
ExitStatus exitStatus = ExitStatus.EXECUTING;
doExecutionRegistration(stepExecution);
getCompositeListener().beforeStep(stepExecution);
open(stepExecution.getExecutionContext());
1.2. 开始执行Step
- 执行Step
- 获取退出状态
- 跟通信stepExecution中的状态
doExecute(stepExecution);
exitStatus = ExitStatus.COMPLETED.and(stepExecution.getExitStatus());
if (stepExecution.isTerminateOnly()) {
throw new JobInterruptedException("JobExecution interrupted.");
}
stepExecution.upgradeStatus(BatchStatus.COMPLETED);
1.3. Step异常处理
stepExecution.upgradeStatus(determineBatchStatus(e));
exitStatus = exitStatus.and(getDefaultExitStatusForFailure(e));
stepExecution.addFailureException(e);
1.4. Step收尾处理
- 计算退出状态
- 更新StepExecutionContext到资源库
- 更新StepExecution到资源库
- 执行steam的close方法
- 释放StepExecution
exitStatus = exitStatus.and(stepExecution.getExitStatus());
stepExecution.setExitStatus(exitStatus);
exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution));
try {
getJobRepository().updateExecutionContext(stepExecution);
} catch (Exception e) {
stepExecution.setStatus(BatchStatus.UNKNOWN);
exitStatus = exitStatus.and(ExitStatus.UNKNOWN);
stepExecution.addFailureException(e);
}
stepExecution.setEndTime(new Date());
stepExecution.setExitStatus(exitStatus);
try {
getJobRepository().update(stepExecution);
}
catch (Exception e) {
stepExecution.setStatus(BatchStatus.UNKNOWN);
stepExecution.setExitStatus(exitStatus.and(ExitStatus.UNKNOWN));
stepExecution.addFailureException(e);
}
try {
close(stepExecution.getExecutionContext());
}
catch (Exception e) {
stepExecution.addFailureException(e);
}
doExecutionRelease();
2. Step业务执行doExecute
doExecute
方法在抽象类AbstractStep
中并未定义,单线程执行方式是在TaskletStep
中执行的
2.1. 开始执行的准备工作
- 设置信息到StepExecutionContext
- 调用stream接口的update方法
- 更新StepExecutionContext到资源库
- 创建信号类
stepExecution.getExecutionContext().put(TASKLET_TYPE_KEY, tasklet.getClass().getName());
stepExecution.getExecutionContext().put(STEP_TYPE_KEY, this.getClass().getName());
stream.update(stepExecution.getExecutionContext());
getJobRepository().updateExecutionContext(stepExecution);
final Semaphore semaphore = createSemaphore();
2.2. 使用重复执行处理类RepeatTemplate
开始执行业务处理
stepOperations.iterate(new StepContextRepeatCallback(stepExecution) {
@Override
public RepeatStatus doInChunkContext(RepeatContext repeatContext, ChunkContext chunkContext) throws Exception {
StepExecution stepExecution = chunkContext.getStepContext().getStepExecution();
interruptionPolicy.checkInterrupted(stepExecution);
RepeatStatus result = new TransactionTemplate(transactionManager, transactionAttribute)
.execute(new ChunkTransactionCallback(chunkContext, semaphore));
chunkListener.afterChunk(chunkContext);
interruptionPolicy.checkInterrupted(stepExecution);
return result;
}
});
3. 启动RepeatTemplate
迭代iterate
方法
3.1. 开始执行迭代方法iterate
- 同步管理器获取RepeatContext
- 初始化Repeat状态为CONTINUABLE
- 执行业务数据
- 处理同步管理器
public RepeatStatus iterate(RepeatCallback callback) {
RepeatContext outer = RepeatSynchronizationManager.getContext();
RepeatStatus result = RepeatStatus.CONTINUABLE;
try {
result = executeInternal(callback);
} finally {
RepeatSynchronizationManager.clear();
if (outer != null) {
RepeatSynchronizationManager.register(outer);
}
}
return result;
}
3.2. 开始执行内部逻辑 executeInternal
方法
- 开始执行前的准备工作
- 检查状态是否是执行中
- 触发
RepeatListener
的open
方法 - 初始化一些状态属性结果等变量
RepeatContext context = start();
boolean running = !isMarkedComplete(context);
for (RepeatListener interceptor : listeners) {
interceptor.open(context);
running = running && !isMarkedComplete(context);
if (!running)
break;
}
RepeatStatus result = RepeatStatus.CONTINUABLE;
RepeatInternalState state = createInternalState(context);
Collection<Throwable> throwables = state.getThrowables();
Collection<Throwable> deferred = new ArrayList<>();
- 执行迭代
- 触发
RepeatListener
的before
方法 - 判断状态,如果还是running 调用
getNextResult
获取结果 - 判断完成的依据是走的
CompletionPolicy
结构的方法
while (running) {
for (int i = 0; i < listeners.length; i++) {
RepeatListener interceptor = listeners[i];
interceptor.before(context);
running = running && !isMarkedComplete(context);
}
if (running) {
try {
result = getNextResult(context, callback, state);
executeAfterInterceptors(context, result);
} catch (Throwable throwable) {
doHandle(throwable, context, deferred);
}
if (isComplete(context, result) || isMarkedComplete(context) || !deferred.isEmpty()) {
running = false;
}
}
}
result = result.and(waitForResults(state));
for (Throwable throwable : throwables) {
doHandle(throwable, context, deferred);
}
state = null;
-
getNextResult
中调用callBack的doInteration
方法
protected RepeatStatus getNextResult(RepeatContext context, RepeatCallback callback, RepeatInternalState state)
throws Throwable {
update(context);
return callback.doInIteration(context);
}
3.3. StepContextRepeatCallback 执行流程
- 执行
doInIteration
- 在同步管理器中获取StepContext
- 在队列中获取一个chunkContext 如果为空创建一个
- 执行
doInChunkContext
- 如果执行失败重新加到队列
- 关闭Step同步管理器
StepContext stepContext = StepSynchronizationManager.register(stepExecution);
ChunkContext chunkContext = attributeQueue.poll();
if (chunkContext == null) {
chunkContext = new ChunkContext(stepContext);
}
try {
return doInChunkContext(context, chunkContext);
} finally {
if (!chunkContext.isComplete()) {
attributeQueue.add(chunkContext);
}
StepSynchronizationManager.close();
}
- 执行
doInChunkContext
这段代码是在2.2中出现过的
- 前期准备检查StepExecution
- 执行事物模板
- 触发chunkListener的afterChunk方法
- 检查stepExecution
StepExecution stepExecution = chunkContext.getStepContext().getStepExecution();
interruptionPolicy.checkInterrupted(stepExecution);
RepeatStatus result = new TransactionTemplate(transactionManager, transactionAttribute)
.execute(new ChunkTransactionCallback(chunkContext, semaphore));
chunkListener.afterChunk(chunkContext);
interruptionPolicy.checkInterrupted(stepExecution);
return result;
3.4 执行TransactionTemplate的execute方法
- 执行事务操作
- 获取一个事物
- 在事物中执行业务逻辑
- 提交事务
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
} else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result = action.doInTransaction(status);
this.transactionManager.commit(status);
return result;
}
2.在事物中执行业务逻辑 Tasklet.ChunkTransactionCallback.doInTransaction
- 同步管理器注册
- 初始化一些属性
- 触发chunkListener的beforeChunk方法
- copy一份stepExecution到旧版本
- 执行tasklet
- 执行Stream接口的update方法
- 更新资源库中的内容
TransactionSynchronizationManager.registerSynchronization(this);
RepeatStatus result = RepeatStatus.CONTINUABLE;
StepContribution contribution = stepExecution.createStepContribution();
chunkListener.beforeChunk(chunkContext);
oldVersion = new StepExecution(stepExecution.getStepName(), stepExecution.getJobExecution());
copy(stepExecution, oldVersion);
try {
result = tasklet.execute(contribution, chunkContext);
if (result == null) {
result = RepeatStatus.FINISHED;
}
} finally {
semaphore.acquire();
locked = true;
stepExecution.apply(contribution);
}
stepExecutionUpdated = true;
stream.update(stepExecution.getExecutionContext());
getJobRepository().updateExecutionContext(stepExecution);
stepExecution.incrementCommitCount();
getJobRepository().update(stepExecution);
return result;
3.4 执行Tasklet的execute方法
这儿的Tasklet可能是我们自己定义的,如果有读写chunk的那么实现类是ChunkOrientedTasklet
- 调用chunkProvider.provide读取数据
- 处理读取到的数据
- 提交处理完成的数据
Chunk<I> inputs = (Chunk<I>) chunkContext.getAttribute(INPUTS_KEY);
if (inputs == null) {
inputs = chunkProvider.provide(contribution);
if (buffering) {
chunkContext.setAttribute(INPUTS_KEY, inputs);
}
}
chunkProcessor.process(contribution, inputs);
chunkProvider.postProcess(contribution, inputs);
if (inputs.isBusy()) {
return RepeatStatus.CONTINUABLE;
}
chunkContext.removeAttribute(INPUTS_KEY);
chunkContext.setComplete();
return RepeatStatus.continueIf(!inputs.isEnd());