4.SpringBatch-单线程TaskletStep详解

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方法

  1. 开始执行前的准备工作
  • 检查状态是否是执行中
  • 触发RepeatListeneropen方法
  • 初始化一些状态属性结果等变量
		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<>();

  1. 执行迭代
  • 触发RepeatListenerbefore方法
  • 判断状态,如果还是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;
  1. getNextResult中调用callBack的doInteration方法
    protected RepeatStatus getNextResult(RepeatContext context, RepeatCallback callback, RepeatInternalState state)
			throws Throwable {
		update(context);
		return callback.doInIteration(context);
	}

3.3. StepContextRepeatCallback 执行流程

  1. 执行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();
	}
  1. 执行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方法

  1. 执行事务操作
  • 获取一个事物
  • 在事物中执行业务逻辑
  • 提交事务
	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());
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值