二、activiti流程运行原理

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

流程启动后会发布一系列事件,并且通过pvm最终转为创建task

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小飞侠fly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值