activiti核心处理类
- RepositoryService:处理流程发布,流程定义等
- RuntimeService:运行时处理类,提供开启流程、获取流程相关的参数,获取流程监听等数据
- FormService:流程自定义表单处理类
- IdentityService:用户权限处理类
- TaskService:任务处理类
- HistoryService:历史数据处理类
- ManagementService:定时任务处理类
启动流程原理
启动流程入口
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(req.getProcessCode());
以startProcessInstanceByKey为例讲解源码
//这里还是熟悉的命令模式
public ProcessInstance startProcessInstanceByKey(String processDefinitionKey) {
return commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, null, null));
}
//直接看StartProcessInstanceCmd的execute方法
public ProcessInstance execute(CommandContext commandContext) {
DeploymentManager deploymentManager = commandContext
.getProcessEngineConfiguration()
.getDeploymentManager();
// Find the process definition
//2.2.1查找流程定义,如果流程定义id不为空,则优先用流程定义id查询,如果存在流程定义key,则还分有租户与没有租户的模式
//流程定义id:ACT_RE_PROCDEF表的ID_,格式为bizOpporProcess:5:10012,即流程定义key+version+主键序列
ProcessDefinitionEntity processDefinition = null;
if (processDefinitionId != null) {
processDefinition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("No process definition found for id = '" + processDefinitionId + "'", ProcessDefinition.class);
}
} else if (processDefinitionKey != null && (tenantId == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId))){
processDefinition = deploymentManager.findDeployedLatestProcessDefinitionByKey(processDefinitionKey);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("No process definition found for key '" + processDefinitionKey +"'", ProcessDefinition.class);
}
} else if (processDefinitionKey != null && tenantId != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) {
processDefinition = deploymentManager.findDeployedLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("No process definition found for key '" + processDefinitionKey +"' for tenant identifier " + tenantId, ProcessDefinition.class);
}
} else {
throw new ActivitiIllegalArgumentException("processDefinitionKey and processDefinitionId are null");
}
// Do not start process a process instance if the process definition is suspended
//2.2.2 判断流程定义是否已经暂停,从这里我们可以知道activiti肯定提供了api来处理流程暂停
if (deploymentManager.isProcessDefinitionSuspended(processDefinition.getId())) {
throw new ActivitiException("Cannot start process instance. Process definition "
+ processDefinition.getName() + " (id = " + processDefinition.getId() + ") is suspended");
}
// Start the process instance
//2.2.3 创建流程
ExecutionEntity processInstance = processDefinition.createProcessInstance(businessKey);
// now set the variables passed into the start command
//2.2.4 初始化流程参数
initializeVariables(processInstance);
// now set processInstance name
if (processInstanceName != null) {
processInstance.setName(processInstanceName);
commandContext.getHistoryManager().recordProcessInstanceNameChange(processInstance.getId(), processInstanceName);
}
//2.2.5 开启流程
processInstance.start();
return processInstance;
}
查找流程定义,以根据流程定义id查找为例
public ProcessDefinitionEntity findDeployedProcessDefinitionById(String processDefinitionId) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
}
// first try the cache
//可以看到这里优先会去缓存中查找,如果没有,再加载,这里代码也写的不太严谨,要是别的源码肯定是会加锁处理的
//cache就是DefaultDeploymentCache,里面封装了Map<String, T> cache为LinkedHashMap
ProcessDefinitionEntity processDefinition = processDefinitionCache.get(processDefinitionId);
if (processDefinition == null) {
processDefinition = Context.getCommandContext()
.getProcessDefinitionEntityManager()
.findProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
}
//2.2.1.1 重点:处理流程定义
processDefinition = resolveProcessDefinition(processDefinition);
}
return processDefinition;
}
处理流程定义
public ProcessDefinitionEntity resolveProcessDefinition(ProcessDefinitionEntity processDefinition) {
String processDefinitionId = processDefinition.getId();
String deploymentId = processDefinition.getDeploymentId();
processDefinition = processDefinitionCache.get(processDefinitionId);
//还是先判断一下缓存中是否有流程定义,如果没有,则发布流程,很任性的写法,spring里面都会加锁,比如来个双重锁校验
if (processDefinition==null) {
//查询的ACT_RE_DEPLOYMENT
DeploymentEntity deployment = Context
.getCommandContext()
.getDeploymentEntityManager()
.findDeploymentById(deploymentId);
deployment.setNew(false);
//重点:发布流程定义
deploy(deployment, null);
//发布之后还是从流程定义缓存中获取,所以在发布的时候肯定是对流程做了处理并且放入缓存中
processDefinition = processDefinitionCache.get(processDefinitionId);
if (processDefinition==null) {
throw new ActivitiException("deployment '"+deploymentId+"' didn't put process definition '"+processDefinitionId+"' in the cache");
}
}
return processDefinition;
}
- 发布流程定义
//虽然第一篇已经讲过,这里还是再放一下加深记忆,又走到了熟悉的流程发布
//从这里我们可以得到这种结论:
//如果在spring框架启动时,流程中有一个改变,则全量发布,并且将流程定义放入缓存;如果没有改变,则会在调用流程时懒加载流程定义
//这里目前从经验来看还是应该加锁处理的,不加锁在并发时有可能会冲突,尤其还是用hashMap
public void deploy(DeploymentEntity deployment, Map<String, Object> deploymentSettings) {
for (Deployer deployer: deployers) {
deployer.deploy(deployment, deploymentSettings);
}
}
//这时会走isNew为false的环节,入参deploymentSettings为null
public void deploy(DeploymentEntity deployment, Map<String, Object> deploymentSettings) {
log.debug("Processing deployment {}", deployment.getName());
List<ProcessDefinitionEntity> processDefinitions = new ArrayList<ProcessDefinitionEntity>();
Map<String, ResourceEntity> resources = deployment.getResources();
Map<String, BpmnModel> bpmnModelMap = new HashMap<String, BpmnModel>();
final ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
for (String resourceName : resources.keySet()) {
log.info("Processing resource {}", resourceName);
if (isBpmnResource(resourceName)) {
ResourceEntity resource = resources.get(resourceName);
byte[] bytes = resource.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
BpmnParse bpmnParse = bpmnParser
.createParse()
.sourceInputStream(inputStream)
.setSourceSystemId(resourceName)
.deployment(deployment)
.name(resourceName);
if (deploymentSettings != null) {
// Schema validation if needed
if (deploymentSettings.containsKey(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED)) {
bpmnParse.setValidateSchema((Boolean) deploymentSettings.get(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED));
}
// Process validation if needed
if (deploymentSettings.containsKey(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED)) {
bpmnParse.setValidateProcess((Boolean) deploymentSettings.get(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED));
}
} else {
//如果没有变动则不校验了
// On redeploy, we assume it is validated at the first deploy
bpmnParse.setValidateSchema(false);
bpmnParse.setValidateProcess(false);
}
//重点:解析流程定义
bpmnParse.execute();
for (ProcessDefinitionEntity processDefinition: bpmnParse.getProcessDefinitions()) {
processDefinition.setResourceName(resourceName);
if (deployment.getTenantId() != null) {
processDefinition.setTenantId(deployment.getTenantId()); // process definition inherits the tenant id
}
String diagramResourceName = getDiagramResourceForProcess(resourceName, processDefinition.getKey(), resources);
// Only generate the resource when deployment is new to prevent modification of deployment resources
// after the process-definition is actually deployed. Also to prevent resource-generation failure every
// time the process definition is added to the deployment-cache when diagram-generation has failed the first time.
if(deployment.isNew()) {
if (processEngineConfiguration.isCreateDiagramOnDeploy() &&
diagramResourceName==null && processDefinition.isGraphicalNotationDefined()) {
try {
byte[] diagramBytes = IoUtil.readInputStream(processEngineConfiguration.
getProcessDiagramGenerator().generateDiagram(bpmnParse.getBpmnModel(), "png", processEngineConfiguration.getActivityFontName(),
processEngineConfiguration.getLabelFontName(),processEngineConfiguration.getAnnotationFontName(), processEngineConfiguration.getClassLoader()), null);
diagramResourceName = getProcessImageResourceName(resourceName, processDefinition.getKey(), "png");
createResource(diagramResourceName, diagramBytes, deployment);
} catch (Throwable t) { // if anything goes wrong, we don't store the image (the process will still be executable).
log.warn("Error while generating process diagram, image will not be stored in repository", t);
}
}
}
processDefinition.setDiagramResourceName(diagramResourceName);
processDefinitions.add(processDefinition);
bpmnModelMap.put(processDefinition.getKey(), bpmnParse.getBpmnModel());
}
}
}
// check if there are process definitions with the same process key to prevent database unique index violation
List<String> keyList = new ArrayList<String>();
for (ProcessDefinitionEntity processDefinition : processDefinitions) {
if (keyList.contains(processDefinition.getKey())) {
throw new ActivitiException("The deployment contains process definitions with the same key '"+ processDefinition.getKey() +"' (process id atrribute), this is not allowed");
}
keyList.add(processDefinition.getKey());
}
CommandContext commandContext = Context.getCommandContext();
ProcessDefinitionEntityManager processDefinitionManager = commandContext.getProcessDefinitionEntityManager();
DbSqlSession dbSqlSession = commandContext.getSession(DbSqlSession.class);
for (ProcessDefinitionEntity processDefinition : processDefinitions) {
List<TimerEntity> timers = new ArrayList<TimerEntity>();
if (deployment.isNew()) {
int processDefinitionVersion;
ProcessDefinitionEntity latestProcessDefinition = null;
if (processDefinition.getTenantId() != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
latestProcessDefinition = processDefinitionManager
.findLatestProcessDefinitionByKeyAndTenantId(processDefinition.getKey(), processDefinition.getTenantId());
} else {
latestProcessDefinition = processDefinitionManager
.findLatestProcessDefinitionByKey(processDefinition.getKey());
}
if (latestProcessDefinition != null) {
processDefinitionVersion = latestProcessDefinition.getVersion() + 1;
} else {
processDefinitionVersion = 1;
}
processDefinition.setVersion(processDefinitionVersion);
processDefinition.setDeploymentId(deployment.getId());
String nextId = idGenerator.getNextId();
String processDefinitionId = processDefinition.getKey()
+ ":" + processDefinition.getVersion()
+ ":" + nextId; // ACT-505
// ACT-115: maximum id length is 64 charcaters
if (processDefinitionId.length() > 64) {
processDefinitionId = nextId;
}
processDefinition.setId(processDefinitionId);
if(commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, processDefinition));
}
removeObsoleteTimers(processDefinition);
addTimerDeclarations(processDefinition, timers);
removeExistingMessageEventSubscriptions(processDefinition, latestProcessDefinition);
addMessageEventSubscriptions(processDefinition);
removeExistingSignalEventSubScription(processDefinition, latestProcessDefinition);
addSignalEventSubscriptions(processDefinition);
dbSqlSession.insert(processDefinition);
addAuthorizations(processDefinition);
if(commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_INITIALIZED, processDefinition));
}
scheduleTimers(timers);
} else {
String deploymentId = deployment.getId();
processDefinition.setDeploymentId(deploymentId);
ProcessDefinitionEntity persistedProcessDefinition = null;
if (processDefinition.getTenantId() == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(processDefinition.getTenantId())) {
persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKey(deploymentId, processDefinition.getKey());
} else {
persistedProcessDefinition = processDefinitionManager.findProcessDefinitionByDeploymentAndKeyAndTenantId(deploymentId, processDefinition.getKey(), processDefinition.getTenantId());
}
if (persistedProcessDefinition != null) {
processDefinition.setId(persistedProcessDefinition.getId());
processDefinition.setVersion(persistedProcessDefinition.getVersion());
processDefinition.setSuspensionState(persistedProcessDefinition.getSuspensionState());
}
}
// Add to cache
DeploymentManager deploymentManager = processEngineConfiguration.getDeploymentManager();
deploymentManager.getProcessDefinitionCache().add(processDefinition.getId(), processDefinition);
addDefinitionInfoToCache(processDefinition, processEngineConfiguration, commandContext);
// Add to deployment for further usage
deployment.addDeployedArtifact(processDefinition);
createLocalizationValues(processDefinition.getId(), bpmnModelMap.get(processDefinition.getKey()).getProcessById(processDefinition.getKey()));
}
}
- 解析流程定义
public BpmnParse execute() {
try {
ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
BpmnXMLConverter converter = new BpmnXMLConverter();
boolean enableSafeBpmnXml = false;
String encoding = null;
if (processEngineConfiguration != null) {
enableSafeBpmnXml = processEngineConfiguration.isEnableSafeBpmnXml();
encoding = processEngineConfiguration.getXmlEncoding();
}
//解析文件流
if (encoding != null) {
bpmnModel = converter.convertToBpmnModel(streamSource, validateSchema, enableSafeBpmnXml, encoding);
} else {
bpmnModel = converter.convertToBpmnModel(streamSource, validateSchema, enableSafeBpmnXml);
}
// XSD validation goes first, then process/semantic validation
if (validateProcess) {
ProcessValidator processValidator = processEngineConfiguration.getProcessValidator();
if (processValidator == null) {
LOGGER.warn("Process should be validated, but no process validator is configured on the process engine configuration!");
} else {
List<ValidationError> validationErrors = processValidator.validate(bpmnModel);
if(validationErrors != null && !validationErrors.isEmpty()) {
StringBuilder warningBuilder = new StringBuilder();
StringBuilder errorBuilder = new StringBuilder();
for (ValidationError error : validationErrors) {
if (error.isWarning()) {
warningBuilder.append(error.toString());
warningBuilder.append("\n");
} else {
errorBuilder.append(error.toString());
errorBuilder.append("\n");
}
}
// Throw exception if there is any error
if (errorBuilder.length() > 0) {
throw new ActivitiException("Errors while parsing:\n" + errorBuilder.toString());
}
// Write out warnings (if any)
if (warningBuilder.length() > 0) {
LOGGER.warn("Following warnings encountered during process validation: " + warningBuilder.toString());
}
}
}
}
// Validation successfull (or no validation)
//针对解析的BpmnModel对象再次处理
createImports();
createItemDefinitions();
createMessages();
createOperations();
//重点:转换流程定义
transformProcessDefinitions();
} catch (Exception e) {
if (e instanceof ActivitiException) {
throw (ActivitiException) e;
} else if (e instanceof XMLException) {
throw (XMLException) e;
} else {
throw new ActivitiException("Error parsing XML", e);
}
}
return this;
}
- 这里想记录一下BpmnModel的结构,有利于我们理解整个流程框架
protected Map<String, List<ExtensionAttribute>> definitionsAttributes = new LinkedHashMap();
//流程定义
protected List<Process> processes = new ArrayList();
//流程节点,key为startevent1这种,value是节点的位置对象
protected Map<String, GraphicInfo> locationMap = new LinkedHashMap();
//流程中的连线,key为flow1
protected Map<String, GraphicInfo> labelLocationMap = new LinkedHashMap();
protected Map<String, List<GraphicInfo>> flowLocationMap = new LinkedHashMap();
protected List<Signal> signals = new ArrayList();
protected Map<String, MessageFlow> messageFlowMap = new LinkedHashMap();
protected Map<String, Message> messageMap = new LinkedHashMap();
protected Map<String, String> errorMap = new LinkedHashMap();
protected Map<String, ItemDefinition> itemDefinitionMap = new LinkedHashMap();
protected Map<String, DataStore> dataStoreMap = new LinkedHashMap();
protected List<Pool> pools = new ArrayList();
protected List<Import> imports = new ArrayList();
protected List<Interface> interfaces = new ArrayList();
protected List<Artifact> globalArtifacts = new ArrayList();
protected List<Resource> resources = new ArrayList();
//命名空间map,xml文件都有这个
protected Map<String, String> namespaceMap = new LinkedHashMap();
//目标对象命名空间
protected String targetNamespace;
protected List<String> userTaskFormTypes;
protected List<String> startEventFormTypes;
protected int nextFlowIdCounter = 1;
- 转换流程定义
protected void transformProcessDefinitions() {
sequenceFlows = new HashMap<String, TransitionImpl>();
for (Process process : bpmnModel.getProcesses()) {
//这里取的流程图上的定义isExecutable
if (process.isExecutable()) {
//重点:解析bpmn文件核心,bpmnParserHandlers中有个parseHandlers是一个HashMap对象,里面包含了各种处理类,共有29个
bpmnParserHandlers.parseElement(this, process);
}
}
if (!processDefinitions.isEmpty()) {
processDI();
}
}
public void parseElement(BpmnParse bpmnParse, BaseElement element) {
if (element instanceof DataObject) {
// ignore DataObject elements because they are processed on Process and Sub process level
return;
}
if (element instanceof FlowElement) {
bpmnParse.setCurrentFlowElement((FlowElement) element);
}
// Execute parse handlers
//获取对应的处理器,也是一种桥梁模式,将行为与对象分离,springMvc中也有这种思想
List<BpmnParseHandler> handlers = parseHandlers.get(element.getClass());
if (handlers == null) {
LOGGER.warn("Could not find matching parse handler for + " + element.getId() + " this is likely a bug.");
} else {
//这里调用的ProcessParseHandler的parse方法
for (BpmnParseHandler handler : handlers) {
handler.parse(bpmnParse, element);
}
}
}
- 解析流程节点
//这里使用的是模板方法模式
public void parse(BpmnParse bpmnParse, BaseElement element) {
T baseElement = (T) element;
//最终还是调用的各个子类的executeParse方法
executeParse(bpmnParse, baseElement);
}
protected void executeParse(BpmnParse bpmnParse, Process process) {
if (process.isExecutable() == false) {
LOGGER.info("Ignoring non-executable process with id='" + process.getId() + "'. Set the attribute isExecutable=\"true\" to deploy this process.");
} else {
bpmnParse.getProcessDefinitions().add(transformProcess(bpmnParse, process));
}
}
protected ProcessDefinitionEntity transformProcess(BpmnParse bpmnParse, Process process) {
ProcessDefinitionEntity currentProcessDefinition = new ProcessDefinitionEntity();
bpmnParse.setCurrentProcessDefinition(currentProcessDefinition);
/*
* Mapping object model - bpmn xml: processDefinition.id -> generated by
* activiti engine processDefinition.key -> bpmn id (required)
* processDefinition.name -> bpmn name (optional)
*/
currentProcessDefinition.setKey(process.getId());
currentProcessDefinition.setName(process.getName());
currentProcessDefinition.setCategory(bpmnParse.getBpmnModel().getTargetNamespace());
currentProcessDefinition.setDescription(process.getDocumentation());
currentProcessDefinition.setProperty(PROPERTYNAME_DOCUMENTATION, process.getDocumentation()); // Kept for backwards compatibility. See ACT-1020
currentProcessDefinition.setTaskDefinitions(new HashMap<String, TaskDefinition>());
currentProcessDefinition.setDeploymentId(bpmnParse.getDeployment().getId());
createExecutionListenersOnScope(bpmnParse, process.getExecutionListeners(), currentProcessDefinition);
createEventListeners(bpmnParse, process.getEventListeners(), currentProcessDefinition);
ExpressionManager expressionManager = bpmnParse.getExpressionManager();
for (String candidateUser : process.getCandidateStarterUsers()) {
currentProcessDefinition.addCandidateStarterUserIdExpression(expressionManager.createExpression(candidateUser));
}
for (String candidateGroup : process.getCandidateStarterGroups()) {
currentProcessDefinition.addCandidateStarterGroupIdExpression(expressionManager.createExpression(candidateGroup));
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Parsing process {}", currentProcessDefinition.getKey());
}
bpmnParse.setCurrentScope(currentProcessDefinition);
//重点:解析流程图中的各个对象
bpmnParse.processFlowElements(process.getFlowElements());
processArtifacts(bpmnParse, process.getArtifacts(), currentProcessDefinition);
// parse out any data objects from the template in order to set up the necessary process variables
Map<String, Object> variables = processDataObjects(bpmnParse, process.getDataObjects(), currentProcessDefinition);
if (null != currentProcessDefinition.getVariables()) {
currentProcessDefinition.getVariables().putAll(variables);
} else {
currentProcessDefinition.setVariables(variables);
}
bpmnParse.removeCurrentScope();
if (process.getIoSpecification() != null) {
IOSpecification ioSpecification = createIOSpecification(bpmnParse, process.getIoSpecification());
currentProcessDefinition.setIoSpecification(ioSpecification);
}
return currentProcessDefinition;
}
流程暂停
public boolean isProcessDefinitionSuspended(String processDefinitionId) {
//这里就是查询ACT_RE_PROCDEF表返回的流程定义,然后判断suspensionState是否为2,为1表示正常,为2表示暂停
return findProcessDefinitionByIdFromDatabase(processDefinitionId).isSuspended();
}
public ProcessDefinitionEntity findProcessDefinitionByIdFromDatabase(String processDefinitionId) {
if (processDefinitionId == null) {
throw new ActivitiIllegalArgumentException("Invalid process definition id : null");
}
//这里查询的ACT_RE_PROCDEF表
ProcessDefinitionEntity processDefinition = Context.getCommandContext()
.getProcessDefinitionEntityManager()
.findProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
}
return processDefinition;
}
开启创建流程定义
public ExecutionEntity createProcessInstance(String businessKey, ActivityImpl initial) {
ExecutionEntity processInstance = null;
if(initial == null) {
//2.2.3.1 传入的initial为空,则调用父类的createProcessInstance()方法
processInstance = (ExecutionEntity) super.createProcessInstance();
}else {
processInstance = (ExecutionEntity) super.createProcessInstanceForInitial(initial);
}
processInstance.setExecutions(new ArrayList<ExecutionEntity>());
processInstance.setProcessDefinition(processDefinition);
// Do not initialize variable map (let it happen lazily)
// Set business key (if any)
if (businessKey != null) {
processInstance.setBusinessKey(businessKey);
}
// Inherit tenant id (if any)
if (getTenantId() != null) {
processInstance.setTenantId(getTenantId());
}
// Reset the process instance in order to have the db-generated process instance id available
processInstance.setProcessInstance(processInstance);
// initialize the template-defined data objects as variables first
Map<String, Object> dataObjectVars = getVariables();
if (dataObjectVars != null) {
processInstance.setVariables(dataObjectVars);
}
String authenticatedUserId = Authentication.getAuthenticatedUserId();
String initiatorVariableName = (String) getProperty(BpmnParse.PROPERTYNAME_INITIATOR_VARIABLE_NAME);
if (initiatorVariableName!=null) {
processInstance.setVariable(initiatorVariableName, authenticatedUserId);
}
if (authenticatedUserId != null) {
processInstance.addIdentityLink(authenticatedUserId, null, IdentityLinkType.STARTER);
}
//记录ACT_HI_PROCINST,ACT_HI_ACTINST并发布相应的事件
Context.getCommandContext().getHistoryManager()
.recordProcessInstanceStart(processInstance);
//发布事件
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, processInstance));
}
return processInstance;
}
创建流程定义
public PvmProcessInstance createProcessInstanceForInitial(ActivityImpl initial) {
//initial为流程解析中的开始节点
if(initial == null) {
throw new ActivitiException("Cannot start process instance, initial activity where the process instance should start is null.");
}
//记ACT_RU_EXECUTION
InterpretableExecution processInstance = newProcessInstance(initial);
processInstance.setProcessDefinition(this);
processInstance.setProcessInstance(processInstance);
//流程初始化:定时任务及事件触发
processInstance.initialize();
InterpretableExecution scopeInstance = processInstance;
List<ActivityImpl> initialActivityStack = getInitialActivityStack(initial);
for (ActivityImpl initialActivity: initialActivityStack) {
if (initialActivity.isScope()) {
scopeInstance = (InterpretableExecution) scopeInstance.createExecution();
scopeInstance.setActivity(initialActivity);
if (initialActivity.isScope()) {
scopeInstance.initialize();
}
}
}
scopeInstance.setActivity(initial);
return processInstance;
}
初始化流程参数
//这里没啥好说的,初始化流程参数,流程参数属于流程全局变量,存在表ACT_RU_VARIABLE及ACT_HI_VARINST
protected void initializeVariables(ExecutionEntity processInstance) {
if (variables != null) {
processInstance.setVariables(variables);
}
}
开启流程,这里我们可以猜测一下,前面都是处理流程定义及流程参数,我们还没处理开启流程的下一步呢,大概率会在这里处理
这里应该使用的是状态模式,经历好几个状态变化,最终到taskCreate,用的太6了
public void start() {
if(startingExecution == null && isProcessInstanceType()) {
startingExecution = new StartingExecution(processDefinition.getInitial());
}
performOperation(AtomicOperation.PROCESS_START);
}
public void performOperation(AtomicOperation executionOperation) {
//是否异步,开始节点不是异步处理节点
if (executionOperation.isAsync(this)) {
scheduleAtomicOperationAsync(executionOperation);
} else {
performOperationSync(executionOperation);
}
}
protected void performOperationSync(AtomicOperation executionOperation) {
Context
.getCommandContext()
.performOperation(executionOperation, this);
}
public void performOperation(AtomicOperation executionOperation, InterpretableExecution execution) {
nextOperations.add(executionOperation);
if (nextOperations.size()==1) {
try {
//放入当前线程的ThreadLocal中,类型为Stack
Context.setExecutionContext(execution);
while (!nextOperations.isEmpty()) {
AtomicOperation currentOperation = nextOperations.removeFirst();
if (log.isTraceEnabled()) {
log.trace("AtomicOperation: {} on {}", currentOperation, this);
}
if (execution.getReplacedBy() == null) {
//执行下一节点
currentOperation.execute(execution);
} else {
currentOperation.execute(execution.getReplacedBy());
}
}
} finally {
Context.removeExecutionContext();
}
}
}
- currentOperation.execute,执行当前状态的处理
public void execute(InterpretableExecution execution) {
ScopeImpl scope = getScope(execution);
List<ExecutionListener> exectionListeners = scope.getExecutionListeners(getEventName());
int executionListenerIndex = execution.getExecutionListenerIndex();
if (exectionListeners.size()>executionListenerIndex) {
execution.setEventName(getEventName());
execution.setEventSource(scope);
ExecutionListener listener = exectionListeners.get(executionListenerIndex);
try {
listener.notify(execution);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new PvmException("couldn't execute event listener : "+e.getMessage(), e);
}
execution.setExecutionListenerIndex(executionListenerIndex+1);
execution.performOperation(this);
} else {
execution.setExecutionListenerIndex(0);
execution.setEventName(null);
execution.setEventSource(null);
//处理结束后设置完成事件
eventNotificationsCompleted(execution);
}
}
– eventNotificationsCompleted
protected void eventNotificationsCompleted(InterpretableExecution execution) {
if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Map<String, Object> variablesMap = null;
try {
variablesMap = execution.getVariables();
} catch (Throwable t) {
// In some rare cases getting the execution variables can fail (JPA entity load failure for example)
// We ignore the exception here, because it's only meant to include variables in the initialized event.
}
//发布事件
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityWithVariablesEvent(ActivitiEventType.ENTITY_INITIALIZED,
execution, variablesMap, false));
Context.getProcessEngineConfiguration().getEventDispatcher()
.dispatchEvent(ActivitiEventBuilder.createProcessStartedEvent(execution, variablesMap, false));
}
ProcessDefinitionImpl processDefinition = execution.getProcessDefinition();
StartingExecution startingExecution = execution.getStartingExecution();
List<ActivityImpl> initialActivityStack = processDefinition.getInitialActivityStack(startingExecution.getInitial());
execution.setActivity(initialActivityStack.get(0));
//设置下一状态
execution.performOperation(PROCESS_START_INITIAL);
}
- 经历了好几个状态,最终会在org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerTake的execute提现
public void execute(InterpretableExecution execution) {
TransitionImpl transition = execution.getTransition();
List<ExecutionListener> executionListeners = transition.getExecutionListeners();
int executionListenerIndex = execution.getExecutionListenerIndex();
if (executionListeners.size()>executionListenerIndex) {
execution.setEventName(org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_TAKE);
execution.setEventSource(transition);
ExecutionListener listener = executionListeners.get(executionListenerIndex);
try {
listener.notify(execution);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new PvmException("couldn't execute event listener : "+e.getMessage(), e);
}
execution.setExecutionListenerIndex(executionListenerIndex+1);
execution.performOperation(this);
} else {
if (log.isDebugEnabled()) {
log.debug("{} takes transition {}", execution, transition);
}
execution.setExecutionListenerIndex(0);
execution.setEventName(null);
execution.setEventSource(null);
ActivityImpl activity = (ActivityImpl) execution.getActivity();
//这里获取了下一个节点
ActivityImpl nextScope = findNextScope(activity.getParent(), transition.getDestination());
execution.setActivity(nextScope);
// Firing event that transition is being taken
//发布事件
if(Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createSequenceFlowTakenEvent(ActivitiEventType.SEQUENCEFLOW_TAKEN, transition.getId(),
activity.getId(), (String) activity.getProperties().get("name") ,(String) activity.getProperties().get("type"), activity.getActivityBehavior().getClass().getCanonicalName(),
nextScope.getId(), (String) nextScope.getProperties().get("name"), (String) nextScope.getProperties().get("type"), nextScope.getActivityBehavior().getClass().getCanonicalName()));
}
execution.performOperation(TRANSITION_CREATE_SCOPE);
}
}
//下一个是AtomicOperationTransitionCreateScope
public void execute(InterpretableExecution execution) {
InterpretableExecution propagatingExecution = null;
ActivityImpl activity = (ActivityImpl) execution.getActivity();
if (activity.isScope()) {
propagatingExecution = (InterpretableExecution) execution.createExecution();
propagatingExecution.setActivity(activity);
propagatingExecution.setTransition(execution.getTransition());
execution.setTransition(null);
execution.setActivity(null);
execution.setActive(false);
log.debug("create scope: parent {} continues as execution {}", execution, propagatingExecution);
propagatingExecution.initialize();
} else {
propagatingExecution = execution;
}
propagatingExecution.performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_START);
}
//下一个又到AbstractEventAtomicOperation,里面listener.notify(execution);保存了ACT_HI_ACTINST表数据......
- 在前面一系列状态处理后,最后生成任务在UserTaskActivityBehavior的execute方法中,可以看到保存了ACT_RU_TASK
public void execute(ActivityExecution execution) throws Exception {
TaskEntity task = TaskEntity.createAndInsert(execution);
task.setExecution(execution);
Expression activeNameExpression = null;
Expression activeDescriptionExpression = null;
Expression activeDueDateExpression = null;
Expression activePriorityExpression = null;
Expression activeCategoryExpression = null;
Expression activeFormKeyExpression = null;
Expression activeSkipExpression = null;
Expression activeAssigneeExpression = null;
Expression activeOwnerExpression = null;
Set<Expression> activeCandidateUserExpressions = null;
Set<Expression> activeCandidateGroupExpressions = null;
if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(userTaskId, execution.getProcessDefinitionId());
activeNameExpression = getActiveValue(taskDefinition.getNameExpression(), DynamicBpmnConstants.USER_TASK_NAME, taskElementProperties);
taskDefinition.setNameExpression(activeNameExpression);
activeDescriptionExpression = getActiveValue(taskDefinition.getDescriptionExpression(), DynamicBpmnConstants.USER_TASK_DESCRIPTION, taskElementProperties);
taskDefinition.setDescriptionExpression(activeDescriptionExpression);
activeDueDateExpression = getActiveValue(taskDefinition.getDueDateExpression(), DynamicBpmnConstants.USER_TASK_DUEDATE, taskElementProperties);
taskDefinition.setDueDateExpression(activeDueDateExpression);
activePriorityExpression = getActiveValue(taskDefinition.getPriorityExpression(), DynamicBpmnConstants.USER_TASK_PRIORITY, taskElementProperties);
taskDefinition.setPriorityExpression(activePriorityExpression);
activeCategoryExpression = getActiveValue(taskDefinition.getCategoryExpression(), DynamicBpmnConstants.USER_TASK_CATEGORY, taskElementProperties);
taskDefinition.setCategoryExpression(activeCategoryExpression);
activeFormKeyExpression = getActiveValue(taskDefinition.getFormKeyExpression(), DynamicBpmnConstants.USER_TASK_FORM_KEY, taskElementProperties);
taskDefinition.setFormKeyExpression(activeFormKeyExpression);
activeSkipExpression = getActiveValue(taskDefinition.getSkipExpression(), DynamicBpmnConstants.TASK_SKIP_EXPRESSION, taskElementProperties);
taskDefinition.setSkipExpression(activeSkipExpression);
activeAssigneeExpression = getActiveValue(taskDefinition.getAssigneeExpression(), DynamicBpmnConstants.USER_TASK_ASSIGNEE, taskElementProperties);
taskDefinition.setAssigneeExpression(activeAssigneeExpression);
activeOwnerExpression = getActiveValue(taskDefinition.getOwnerExpression(), DynamicBpmnConstants.USER_TASK_OWNER, taskElementProperties);
taskDefinition.setOwnerExpression(activeOwnerExpression);
activeCandidateUserExpressions = getActiveValueSet(taskDefinition.getCandidateUserIdExpressions(), DynamicBpmnConstants.USER_TASK_CANDIDATE_USERS, taskElementProperties);
taskDefinition.setCandidateUserIdExpressions(activeCandidateUserExpressions);
activeCandidateGroupExpressions = getActiveValueSet(taskDefinition.getCandidateGroupIdExpressions(), DynamicBpmnConstants.USER_TASK_CANDIDATE_GROUPS, taskElementProperties);
taskDefinition.setCandidateGroupIdExpressions(activeCandidateGroupExpressions);
} else {
activeNameExpression = taskDefinition.getNameExpression();
activeDescriptionExpression = taskDefinition.getDescriptionExpression();
activeDueDateExpression = taskDefinition.getDueDateExpression();
activePriorityExpression = taskDefinition.getPriorityExpression();
activeCategoryExpression = taskDefinition.getCategoryExpression();
activeFormKeyExpression = taskDefinition.getFormKeyExpression();
activeSkipExpression = taskDefinition.getSkipExpression();
activeAssigneeExpression = taskDefinition.getAssigneeExpression();
activeOwnerExpression = taskDefinition.getOwnerExpression();
activeCandidateUserExpressions = taskDefinition.getCandidateUserIdExpressions();
activeCandidateGroupExpressions = taskDefinition.getCandidateGroupIdExpressions();
}
task.setTaskDefinition(taskDefinition);
if (activeNameExpression != null) {
String name = null;
try {
name = (String) activeNameExpression.getValue(execution);
} catch (ActivitiException e) {
name = activeNameExpression.getExpressionText();
LOGGER.warn("property not found in task name expression " + e.getMessage());
}
task.setName(name);
}
if (activeDescriptionExpression != null) {
String description = null;
try {
description = (String) activeDescriptionExpression.getValue(execution);
} catch (ActivitiException e) {
description = activeDescriptionExpression.getExpressionText();
LOGGER.warn("property not found in task description expression " + e.getMessage());
}
task.setDescription(description);
}
if (activeDueDateExpression != null) {
Object dueDate = activeDueDateExpression.getValue(execution);
if (dueDate != null) {
if (dueDate instanceof Date) {
task.setDueDate((Date) dueDate);
} else if (dueDate instanceof String) {
BusinessCalendar businessCalendar = Context
.getProcessEngineConfiguration()
.getBusinessCalendarManager()
.getBusinessCalendar(taskDefinition.getBusinessCalendarNameExpression().getValue(execution).toString());
task.setDueDate(businessCalendar.resolveDuedate((String) dueDate));
} else {
throw new ActivitiIllegalArgumentException("Due date expression does not resolve to a Date or Date string: " +
activeDueDateExpression.getExpressionText());
}
}
}
if (activePriorityExpression != null) {
final Object priority = activePriorityExpression.getValue(execution);
if (priority != null) {
if (priority instanceof String) {
try {
task.setPriority(Integer.valueOf((String) priority));
} catch (NumberFormatException e) {
throw new ActivitiIllegalArgumentException("Priority does not resolve to a number: " + priority, e);
}
} else if (priority instanceof Number) {
task.setPriority(((Number) priority).intValue());
} else {
throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " +
activePriorityExpression.getExpressionText());
}
}
}
if (activeCategoryExpression != null) {
final Object category = activeCategoryExpression.getValue(execution);
if (category != null) {
if (category instanceof String) {
task.setCategory((String) category);
} else {
throw new ActivitiIllegalArgumentException("Category expression does not resolve to a string: " +
activeCategoryExpression.getExpressionText());
}
}
}
if (activeFormKeyExpression != null) {
final Object formKey = activeFormKeyExpression.getValue(execution);
if (formKey != null) {
if (formKey instanceof String) {
task.setFormKey((String) formKey);
} else {
throw new ActivitiIllegalArgumentException("FormKey expression does not resolve to a string: " +
activeFormKeyExpression.getExpressionText());
}
}
}
boolean skipUserTask = SkipExpressionUtil.isSkipExpressionEnabled(execution, activeSkipExpression) &&
SkipExpressionUtil.shouldSkipFlowElement(execution, activeSkipExpression);
if (!skipUserTask) {
handleAssignments(activeAssigneeExpression, activeOwnerExpression, activeCandidateUserExpressions,
activeCandidateGroupExpressions, task, execution);
}
task.fireEvent(TaskListener.EVENTNAME_CREATE);
// All properties set, now firing 'create' events
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.TASK_CREATED, task));
}
if (skipUserTask) {
task.complete(null, false);
}
}
总结
启动流程保存的表:
运行时:ACT_RU_TASK,ACT_RU_VARIABLE,ACT_RU_IDENTITYLINK
历史表:ACT_HI_PROCINST,ACT_HI_ACTINST,ACT_HI_VARINST,ACT_HI_IDENTITYLINK,ACT_HI_TASKINST