activiti学习(九)——对象解析器原理

在《activiti学习(六)——从bpmn文件转化为bpmnModel的过程》提到过,activiti会把bpmn图中的元素转化到bpmnModel中,然后再通过对象解析器,把各元素解析流程虚拟机识别的对象。本章主要讲解这个解析过程。

activiti的元素非常多,这里我们仅介绍一下process及内部userTask、sequenceFlow的解析,其他元素请自行研究。简单来讲,流程虚拟机会把流程中的活动解析为ActivityImpl对象,把连线解析为TransitionImpl对象,并为他们设置对应的行为。当流程执行到某个对象时,就会执行该对象对应的行为。

对象解析器的初始化

首先看看activiti内置的对象解析器,在ProcessEngineConfigurationImpl.java:

  protected void init() {
    //......省略
    initServices();
    initIdGenerator();
    initDeployers();
    initJobHandlers();
    initJobExecutor();
    //......省略
  }

protected void initDeployers() {
    if (this.deployers==null) {
      this.deployers = new ArrayList<Deployer>();
      if (customPreDeployers!=null) {
        this.deployers.addAll(customPreDeployers);
      }
      this.deployers.addAll(getDefaultDeployers());
      if (customPostDeployers!=null) {
        this.deployers.addAll(customPostDeployers);
      }
    }
    //......省略
  }

  protected Collection< ? extends Deployer> getDefaultDeployers() {
//......省略
    
    List<BpmnParseHandler> parseHandlers = new ArrayList<BpmnParseHandler>();
    if(getPreBpmnParseHandlers() != null) {
      parseHandlers.addAll(getPreBpmnParseHandlers());
    }
    parseHandlers.addAll(getDefaultBpmnParseHandlers());
    if(getPostBpmnParseHandlers() != null) {
      parseHandlers.addAll(getPostBpmnParseHandlers());
    }
    
    BpmnParseHandlers bpmnParseHandlers = new BpmnParseHandlers();
    bpmnParseHandlers.addHandlers(parseHandlers);
    bpmnParser.setBpmnParserHandlers(bpmnParseHandlers);
    
    bpmnDeployer.setBpmnParser(bpmnParser);
    
    defaultDeployers.add(bpmnDeployer);
    return defaultDeployers;
  }

  protected List<BpmnParseHandler> getDefaultBpmnParseHandlers() {
    List<BpmnParseHandler> bpmnParserHandlers = new ArrayList<BpmnParseHandler>();
    bpmnParserHandlers.add(new BoundaryEventParseHandler());
    bpmnParserHandlers.add(new BusinessRuleParseHandler());
    bpmnParserHandlers.add(new CallActivityParseHandler());
    bpmnParserHandlers.add(new CancelEventDefinitionParseHandler());
    bpmnParserHandlers.add(new CompensateEventDefinitionParseHandler());
    bpmnParserHandlers.add(new EndEventParseHandler());
    bpmnParserHandlers.add(new ErrorEventDefinitionParseHandler());
    bpmnParserHandlers.add(new EventBasedGatewayParseHandler());
    bpmnParserHandlers.add(new ExclusiveGatewayParseHandler());
    bpmnParserHandlers.add(new InclusiveGatewayParseHandler());
    bpmnParserHandlers.add(new IntermediateCatchEventParseHandler());
    bpmnParserHandlers.add(new IntermediateThrowEventParseHandler());
    bpmnParserHandlers.add(new ManualTaskParseHandler());
    bpmnParserHandlers.add(new MessageEventDefinitionParseHandler());
    bpmnParserHandlers.add(new ParallelGatewayParseHandler());
    bpmnParserHandlers.add(new ProcessParseHandler());
    bpmnParserHandlers.add(new ReceiveTaskParseHandler());
    bpmnParserHandlers.add(new ScriptTaskParseHandler());
    bpmnParserHandlers.add(new SendTaskParseHandler());
    bpmnParserHandlers.add(new SequenceFlowParseHandler());
    bpmnParserHandlers.add(new ServiceTaskParseHandler());
    bpmnParserHandlers.add(new SignalEventDefinitionParseHandler());
    bpmnParserHandlers.add(new StartEventParseHandler());
    bpmnParserHandlers.add(new SubProcessParseHandler());
    bpmnParserHandlers.add(new EventSubProcessParseHandler());
    bpmnParserHandlers.add(new TaskParseHandler());
    bpmnParserHandlers.add(new TimerEventDefinitionParseHandler());
    bpmnParserHandlers.add(new TransactionParseHandler());
    bpmnParserHandlers.add(new UserTaskParseHandler());
    
    if (customDefaultBpmnParseHandlers != null) {
    //......省略
    //自定义对象解析器,替换默认对象解析器
    }
    
    // History
    for (BpmnParseHandler handler : getDefaultHistoryParseHandlers()) {
      bpmnParserHandlers.add(handler);
    }
    
    return bpmnParserHandlers;
  }

第5行初始化部署器,17行获取默认部署器,29-35行为添加自定义前置对象解析器、默认对象解析器和后置对象解析器。48-77行添加具体的默认对象解析器,79-82行用自定义对象解析器替换默认对象解析器,85-87行添加历史对象解析器。

在《activiti学习(六)——从bpmn文件转化为bpmnModel的过程》中,我们曾经追踪BpmnParse.java:

  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) {
        ......
        //省略校验bpmnModel有效性
      }
      
      // Validation successfull (or no validation)
      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;
  }

  protected void transformProcessDefinitions() {
    sequenceFlows = new HashMap<String, TransitionImpl>();
    for (Process process : bpmnModel.getProcesses()) {
      if (process.isExecutable()) {
        bpmnParserHandlers.parseElement(this, process);
      }
    }

    if (!processDefinitions.isEmpty()) {
      processDI();
    }
  }

31行transformProcessDefinitions()开始执行对象解析的转化。48-52行对bpmnModel中的每个设置了isExecutable="true"的process进行解析。调用BpmnParseHandlers.parseElement()方法,跟踪BpmnParseHandlers.java:

  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
    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 {
      for (BpmnParseHandler handler : handlers) {
        handler.parse(bpmnParse, element);
      }
    }
  }

13行获取元素对应的对象解析器。

process解析

以下们解析process为例,这里则会获取ProcessParseHandler。接着19行handler.parse(bpmnParse, element)调用跳转到AbstractActivityBpmnParseHandler.java:

  public void parse(BpmnParse bpmnParse, BaseElement element) {
    super.parse(bpmnParse, element);
    
    if (element instanceof Activity
            && ((Activity) element).getLoopCharacteristics() != null) {
      createMultiInstanceLoopCharacteristics(bpmnParse, (Activity) element);
    }
  }

第2行调用父类的parse方法,跟踪AbstractFlowNodeBpmnParseHandler.java:

  public void parse(BpmnParse bpmnParse, BaseElement element) {
    super.parse(bpmnParse, element);
    createExecutionListenersOnScope(bpmnParse, ((FlowNode) element).getExecutionListeners(), findActivity(bpmnParse, element.getId()));
  }

第2行调用父类的parse方法,跟踪AbstractBpmnParseHandler.java:

  public void parse(BpmnParse bpmnParse, BaseElement element) {
    T baseElement = (T) element;
    executeParse(bpmnParse, baseElement);
  }

上面第3行的executeParse方法调用内置process对象解析器ProcessParseHandler,跟踪ProcessParseHandler.java:

  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);

    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;
  }

第4行把transformProcess中解析出来的流程定义实体添加到bpmnParse的流程定义实体集合中。13-19行设置process的属性,20-21行创建对应的执行监听器和事件转发器。37行setCurrentScope把当前处理的流程定义压入栈中,处理子元素时使用。39行处理process下的子元素。

接下来跟踪bpmnParse.processFlowElements(process.getFlowElements()),查看BpmnParse.java:

  public void processFlowElements(Collection<FlowElement> flowElements) {
    List<SequenceFlow> sequenceFlowToParse = new ArrayList<SequenceFlow>();
    List<BoundaryEvent> boundaryEventsToParse = new ArrayList<BoundaryEvent>();
    List<FlowElement> defferedFlowElementsToParse = new ArrayList<FlowElement>();

    for (FlowElement flowElement : flowElements) {
      if (flowElement instanceof SequenceFlow) {
        sequenceFlowToParse.add((SequenceFlow) flowElement);
      } else if (flowElement instanceof BoundaryEvent) {
        boundaryEventsToParse.add((BoundaryEvent) flowElement);
      } else if (flowElement instanceof Event) {
        defferedFlowElementsToParse.add(flowElement);
      } else {
        bpmnParserHandlers.parseElement(this, flowElement);
      }
    }
    // Deferred elements
    for (FlowElement flowElement : defferedFlowElementsToParse) {
      bpmnParserHandlers.parseElement(this, flowElement);
    }
    // Boundary events are parsed after all the regular activities are parsed
    for (BoundaryEvent boundaryEvent : boundaryEventsToParse) {
      bpmnParserHandlers.parseElement(this, boundaryEvent);
    }
    // sequence flows
    for (SequenceFlow sequenceFlow : sequenceFlowToParse) {
      bpmnParserHandlers.parseElement(this, sequenceFlow);
    }
  }

7-12行分别把连线、边界事件、事件存起来,在18-28行处理。14行先处理其他元素(例如userTask)之后再处理它们。因为连线、事件这些和具体的活动相关,因此先实例化活动元素,然后实例化连线、事件元素时,再把它们和活动关联起来。

userTask解析

接下来我们分别看userTask对象解析器。解析process子元素的bpmnParserHandlers.parseElement与前面解析process调用情况类似,仅在AbstractBpmnParseHandler.java时根据多态会调用UserTaskParseHandle。我们先看UserTaskParseHandler.java

  protected void executeParse(BpmnParse bpmnParse, UserTask userTask) {
    ActivityImpl activity = createActivityOnCurrentScope(bpmnParse, userTask, BpmnXMLConstants.ELEMENT_TASK_USER);
    
    activity.setAsync(userTask.isAsynchronous());
    activity.setExclusive(!userTask.isNotExclusive()); 
    
    TaskDefinition taskDefinition = parseTaskDefinition(bpmnParse, userTask, userTask.getId(), (ProcessDefinitionEntity) bpmnParse.getCurrentScope().getProcessDefinition());
    activity.setProperty(PROPERTY_TASK_DEFINITION, taskDefinition);
    activity.setActivityBehavior(bpmnParse.getActivityBehaviorFactory().createUserTaskActivityBehavior(userTask, taskDefinition));
  }

第2行为userTask创建ActivitiImpl,第7行为userTask创建任务定义,第9行为userTask设置行为。我们跟踪createActivityOnCurrentScope看其如何创建ActivitiImpl。查看AbstractBpmnParseHandler.java:

  public ActivityImpl createActivityOnCurrentScope(BpmnParse bpmnParse, FlowElement flowElement, String xmlLocalName) {
    return createActivityOnScope(bpmnParse, flowElement, xmlLocalName, bpmnParse.getCurrentScope());
  }
  
  public ActivityImpl createActivityOnScope(BpmnParse bpmnParse, FlowElement flowElement, String xmlLocalName, ScopeImpl scopeElement) {
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Parsing activity {}", flowElement.getId());
    }
    
    ActivityImpl activity = scopeElement.createActivity(flowElement.getId());
    bpmnParse.setCurrentActivity(activity);

    activity.setProperty("name", flowElement.getName());
    activity.setProperty("documentation", flowElement.getDocumentation());
    if (flowElement instanceof Activity) {
      Activity modelActivity = (Activity) flowElement;
      activity.setProperty("default", modelActivity.getDefaultFlow());
      if(modelActivity.isForCompensation()) {
        activity.setProperty(PROPERTYNAME_IS_FOR_COMPENSATION, true);        
      }
    } else if (flowElement instanceof Gateway) {
      activity.setProperty("default", ((Gateway) flowElement).getDefaultFlow());
    }
    activity.setProperty("type", xmlLocalName);
    return activity;
  }
  

第10行创建ActivityImpl,15-23行判断如果属于活动对象或网关对象,对应不同的属性设置。这里的scopeElement就是process,跟踪scopeElement.createActivity,查看ScopeImpl.java:

  public ActivityImpl createActivity(String activityId) {
    ActivityImpl activity = new ActivityImpl(activityId, processDefinition);
    if (activityId!=null) {
      if (processDefinition.findActivity(activityId) != null) {
        throw new PvmException("duplicate activity id '" + activityId + "'");
      }
      namedActivities.put(activityId, activity);
    }
    activity.setParent(this);
    activities.add(activity);
    return  activity;
  }

第2行新建ActivityImpl对象,4-6行判断是否有重复命名。

SequenceFlow解析

接下来看看连线的解析,SequenceFlowParseHandler.java:

  protected void executeParse(BpmnParse bpmnParse, SequenceFlow sequenceFlow) {
    ScopeImpl scope = bpmnParse.getCurrentScope();

    ActivityImpl sourceActivity = scope.findActivity(sequenceFlow.getSourceRef());
    ActivityImpl destinationActivity = scope.findActivity(sequenceFlow.getTargetRef());

    Expression skipExpression;
    if (StringUtils.isNotEmpty(sequenceFlow.getSkipExpression())) {
      ExpressionManager expressionManager = bpmnParse.getExpressionManager();
      skipExpression = expressionManager.createExpression(sequenceFlow.getSkipExpression());
    } else {
      skipExpression = null;
    }
    
    TransitionImpl transition = sourceActivity.createOutgoingTransition(sequenceFlow.getId(), skipExpression);
    bpmnParse.getSequenceFlows().put(sequenceFlow.getId(), transition);
    transition.setProperty("name", sequenceFlow.getName());
    transition.setProperty("documentation", sequenceFlow.getDocumentation());
    transition.setDestination(destinationActivity);

    if (StringUtils.isNotEmpty(sequenceFlow.getConditionExpression())) {
      Condition expressionCondition = new UelExpressionCondition(sequenceFlow.getConditionExpression());
      transition.setProperty(PROPERTYNAME_CONDITION_TEXT, sequenceFlow.getConditionExpression());
      transition.setProperty(PROPERTYNAME_CONDITION, expressionCondition);
    }

    createExecutionListenersOnTransition(bpmnParse, sequenceFlow.getExecutionListeners(), transition);
  }

4-5行获取连线的首尾两个节点,7-13行为设置跳过表达式,15行通过起始节点创建TransitionImpl,21-25行设置条件表达式,27行设置执行监听器。表达式相关的内容后面的文章再进行分析。

发布了39 篇原创文章 · 获赞 5 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/sadoshi/article/details/105015831
今日推荐