Activiti流程定义缓存源码分析8-流程缓存自定义原理

南楼画角 提交于 2020-02-08 02:45:51

上面我们浓墨重彩地讲述了自定义节点缓存类以及将其注入流程引擎配置类实例的过程,可能读者有个疑问?节点定义的缓存数据格式是什么呢?流程引擎执行节点的时候,又是如何获取并解析节点所缓存的数据呢?这也是接下来我们需要重点讲解的地方。任务节点的缓存信息当然是在任务需要执行的地方进行解析了,比如任务的完成操作或者任务节点的入库操作。关于这一点读者可以参考之前的章节。在此我们直接找到任务节点的行为执行类UserTaskActivityBehavior的执行函数execute,相关代码如代码清单x-所示。

代码清单x-UserTaskActivityBehavior.java

---------------------------------------------------------------------------------------------------------------------------

  public void execute(ActivityExecution execution) throws Exception {

  ...

if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {#-1

ObjectNode taskElementProperties = Context.getBpmnOverrideElementProperties(userTaskId, execution.getProcessDefinitionId()); #-2

      activeNameExpression = getActiveValue(taskDefinition.getNameExpression(), "userTaskName", taskElementProperties); #-3

      taskDefinition.setNameExpression(activeNameExpression); #-4

      ...

  }

Expression getActiveValue(Expression originalValue, String propertyName, ObjectNode taskElementProperties) {

    Expression activeValue = originalValue;

    if (taskElementProperties != null) {

      JsonNode overrideValueNode = taskElementProperties.get(propertyName);

      if (overrideValueNode != null) {

        if (overrideValueNode.isNull()) {

          activeValue = null;

        } else {

          activeValue = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(overrideValueNode.asText());

        }

      }

    }

    return activeValue;

  }

---------------------------------------------------------------------------------------------------------------------------

上面的代码处理逻辑非常的复杂,我们暂且将关注点放到节点缓存的获取操作中,首先#-1验证引擎是否开启了节点缓存(参考代码清单x中的配置属性值),如果流程引擎开启了节点缓存功能,则首先从缓存中查找节点的缓存数据,并对其进行解析和运用如#-4所示。#-2和#-3完成从缓存中取出数据并对taskDefinition属性进行填充。由于该过程涉及到了缓存数据的获取和解析,所以我们应该重点学习该过程的处理流程。首先来看看这个方法的时序图,如图x-所示。

      

图x-getBpmnOverrideElementProperties函数执行时序图

看到图x-我们才知道什么叫山路十八弯,饶了半天才真正的切入主题,比如缓存数据的获取以及根据任务节点id进行必要属性的获取工作。我们根据上面的时序图来分析一下execute函数究竟做了工作?根据上面的时序图我们尝试梳理整个处理过程如下。

  1. 获取缓存中的数据。当进入getBpmnOverrideElementProperties方法后首先根据流程定义id从缓存中获取数据,获取缓存数据的时候,Activiti在当前函数getBpmnOverrideContext中做了一层功能架构。首先调用函数getBpmnOverrideContext确保当前类中的bpmnOverrideContextThreadLocal成员变量已经被初始化,然后委托DeploymentManager类进行节点缓存的获取工作,最后调用addBpmnOverrideElement函数将获取到的节点数据进行缓存。需要注意bpmnOverrideContextThreadLocal为ThreadLocal类型,ThreadLocal是为了解决线程安全的问题而设计的,该类内部维护一个Map集合,用于存储每一个线程变量的副本,Map中的键为当前线程对象,值为对应线程的变量副本,由于键是不能重复的,从而达到了线程安全的目的。
  2. 根据任务节点的id值从缓存中查找需要的数据集合。经过步骤一之后,流程中所有的节点缓存数据已经被获取到了,接下来的工作就是对获取到的数据进行解析,首先委托DynamicBpmnService类中的函数getBpmnElementProperties进行指定值的获取,节点数据的获取逻辑也很简单,首先调用getBpmnNode方法获取ObjectNode对象中key为“bpmn”的值,如果获取到,则以id值为查询条件并从查询结果中获取该id值下面所有的数据集合并返回,以方便#-3函数进行使用。
  3. #-3函数进行该节点下配置的所有缓存属性值的获取工作如getActiveValue函数所示。该函数根据指定的属性从集合中获取相应的值,如果获取到值则创建表达式,形如${shareniu}。由此可知,节点中的缓存数据值是可以使用Juel表达式的。关于用户节点可以配置缓存的key都定义在DynamicBpmnConstants接口中。由于上面所涉及到的函数处理逻辑都很简单,读者有兴趣可以结合时序图x-进行源码跟进学习。

技术团队支持:盘古BPM工作流平台

具体效果参考盘古BPM

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!