// 接口非常简单,用来执行一个 Command// 实现类为 CommandExecutorImplpublicinterfaceCommandExecutor{/**
* @return the default {@link CommandConfig}, used if none is provided.
*/CommandConfiggetDefaultConfig();/**
* Execute a command with the specified {@link CommandConfig}.
*/<T>Texecute(CommandConfigconfig,Command<T>command);/**
* Execute a command with the default {@link CommandConfig}.
*/<T>Texecute(Command<T>command);}
// 这个拦截器用来创建 contextpublic<T>Texecute(CommandConfigconfig,Command<T>command){CommandContextcontext=Context.getCommandContext();booleancontextReused=false;// We need to check the exception, because the transaction can be in a// rollback state, and some other command is being fired to compensate (eg. decrementing job retries)// context 不复用, 需要创建新的 contextif(!config.isContextReusePossible()||context==null||context.getException()!=null){context=commandContextFactory.createCommandContext(command);}else{log.debug("Valid context found. Reusing it for the current command '{}'",command.getClass().getCanonicalName());// 设置复用contextReused=true;context.setReused(true);}try{// Push on stack// 放入栈中,可以通过 Context 来获取Context.setCommandContext(context);Context.setProcessEngineConfiguration(processEngineConfiguration);// 执行下一个拦截器returnnext.execute(config,command);}catch(Throwablee){// 设置异常// 需要注意的是,如果执行有异常,异常会保留在 context 中// 当有多个 context 时,后面 context 的异常,不会传递到前面的 contextcontext.exception(e);}finally{try{// 如果不复用,关闭 contextif(!contextReused){// 执行语句,但不会提交事务context.close();}}finally{// Pop from stack// 从栈中移除Context.removeCommandContext();Context.removeProcessEngineConfiguration();Context.removeBpmnOverrideContext();}}returnnull;}
// 这个拦截器用来创建 transactionContext// 与 spring 集成时,会有另外一个拦截器 SpringTransactionInterceptor 来开启事务public<T>Texecute(CommandConfigconfig,Command<T>command){CommandContextcommandContext=Context.getCommandContext();// Storing it in a variable, to reference later (it can change during command execution)booleanisReused=commandContext.isReused();try{if(transactionContextFactory!=null&&!isReused){// 创建 transactionContextTransactionContexttransactionContext=transactionContextFactory.openTransactionContext(commandContext);Context.setTransactionContext(transactionContext);// 添加关闭监听器,在关闭时会提交事务,在异常时会回滚事务commandContext.addCloseListener(newTransactionCommandContextCloseListener(transactionContext));}// 执行下一个拦截器returnnext.execute(config,command);}finally{if(transactionContextFactory!=null&&!isReused){Context.removeTransactionContext();}}}
// 这个拦截器负责执行命令public<T>Texecute(finalCommandConfigconfig,finalCommand<T>command){finalCommandContextcommandContext=Context.getCommandContext();// Execute the command.// This will produce operations that will be put on the agenda.// 添加命令到 Agenda 中, 这里的设计很精妙,可以在一个命令中执行另外的命令commandContext.getAgenda().planOperation(newRunnable(){@Overridepublicvoidrun(){commandContext.setResult(command.execute(commandContext));}});// Run loop for agenda// 取出命令来执行executeOperations(commandContext);// At the end, call the execution tree change listeners.// TODO: optimization: only do this when the tree has actually changed (ie check dbSqlSession).if(commandContext.hasInvolvedExecutions()){Context.getAgenda().planExecuteInactiveBehaviorsOperation();executeOperations(commandContext);}// 获取结果return(T)commandContext.getResult();}// 取出命令来执行protectedvoidexecuteOperations(finalCommandContextcommandContext){while(!commandContext.getAgenda().isEmpty()){Runnablerunnable=commandContext.getAgenda().getNextOperation();executeOperation(runnable);}}