Activiti UEL表达式是如何与Spring 的容器整合起来的

Activiti UEL 表达式

UEL表达式到底是什么呢?

UEL是java EE6规范的一部分,UEL(Unified Expression Language)即统一表达式语言,activiti支持两个UEL表达式:UEL-value和UEL-method

Activiti使用UEL进行表达式解析(有关详细信息,请参阅EE6规范

Activiti 如何使用UEL表达式获取Spring 容器中的bean?

答案在activiti-spring.jar中

SpringExpressionManager.java //spring表达式管理类

public class SpringExpressionManager extends ExpressionManager {
  //应用上下文
  protected ApplicationContext applicationContext;

  public SpringExpressionManager(ApplicationContext applicationContext, Map<Object, Object> beans) {
    super(beans);//这个beans是流程引擎中的beans
    this.applicationContext = applicationContext;
  }

  @Override
  protected ELResolver createElResolver(VariableScope variableScope) {
    //复合el表达式
    CompositeELResolver compositeElResolver = new CompositeELResolver();
    compositeElResolver.add(new VariableScopeElResolver(variableScope));

    //判断beans是否为空
    if (beans != null) {
      // 在表达式中只暴露流程引擎中的beans
      compositeElResolver.add(new ReadOnlyMapELResolver(beans));
    } else {
      // 在表达式中暴露整个application-context
      compositeElResolver.add(new ApplicationContextElResolver(applicationContext));
    }

    //添加数组解析器
    compositeElResolver.add(new ArrayELResolver());
    //添加集合解析器
    compositeElResolver.add(new ListELResolver());
    //添加map解析器
    compositeElResolver.add(new MapELResolver());
    //添加json格式的数据解析器 like {key:value,...} or [1,2,3,4,...]
    compositeElResolver.add(new JsonNodeELResolver());
    //添加bean解析器
    compositeElResolver.add(new BeanELResolver());
    return compositeElResolver;
  }

在ProcessEngineConfigurationImpl.java中调用

public class ProcessEngineFactoryBean implements FactoryBean<ProcessEngine>, DisposableBean, ApplicationContextAware {
  ...
  protected void configureExpressionManager() {
    if (processEngineConfiguration.getExpressionManager() == null && applicationContext != null) {
      processEngineConfiguration.setExpressionManager(new SpringExpressionManager(applicationContext, processEngineConfiguration.getBeans()));
    }
  }
  ...
}

使用表达式

Activiti的Expression 接口

public interface Expression extends Serializable {

  // variableScope 为变量作用域
  Object getValue(VariableScope variableScope);

  void setValue(Object value, VariableScope variableScope);

  String getExpressionText();

}

在代码中的具体使用

//获取表达式对象
//execution 为 VariableScope 的实现类 用于从不同的变量作用域中取变量
Expression expression = expressionManager.createExpression("${bean.id}");
      businessKey = expression.getValue(execution).toString();

为什么有VariableScope

因为Activiti中有很多流程,每一个流程都有很多变量,使用变量的时候肯定不能去拿其他流程的变量,为了更好的管理在表达式中使用变量,所以这里就有了一个变量作用域的概念

通过变量作用域获得EL上下文

public class ExpressionManager {
...
    public ELContext getElContext(VariableScope variableScope) {
        ELContext elContext = null;
        if (variableScope instanceof VariableScopeImpl) {
          VariableScopeImpl variableScopeImpl = (VariableScopeImpl) variableScope;
          elContext = variableScopeImpl.getCachedElContext();
        }

        if (elContext == null) {
          //如果没有就创建一个EL上下文
          elContext = createElContext(variableScope);
          if (variableScope instanceof VariableScopeImpl) {
            ((VariableScopeImpl) variableScope).setCachedElContext(elContext);
          }
        }

        return elContext;
    }
...
}

VariableScope 的实现类
这里写图片描述

实现类就只要有三个类

  • NoExecutionVariableScope.java
  • TaskEntityImpl.java
  • ExecutionEntityImpl.java

其中VariableScopeImpl 是个抽象类,这里使用了模板模式

需要子类实现的方法

protected abstract Collection<VariableInstanceEntity> loadVariableInstances();

protected abstract VariableScopeImpl getParentVariableScope();

protected abstract void initializeVariableInstanceBackPointer(VariableInstanceEntity variableInstance);

protected abstract VariableInstanceEntity getSpecificVariable(String variableName);

JUEL实现类

public class JuelExpression implements Expression {

  protected String expressionText;
  protected ValueExpression valueExpression;

  public JuelExpression(ValueExpression valueExpression, String expressionText) {
    this.valueExpression = valueExpression;
    this.expressionText = expressionText;
  }

  public Object getValue(VariableScope variableScope) {
    //获取值的时候都要通过variableScope获取上下文
    ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext(variableScope);
    try {
      ExpressionGetInvocation invocation = new ExpressionGetInvocation(valueExpression, elContext);
      Context.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(invocation);
      return invocation.getInvocationResult();
    } catch (PropertyNotFoundException pnfe) {
      throw new ActivitiException("Unknown property used in expression: " + expressionText, pnfe);
    } catch (MethodNotFoundException mnfe) {
      throw new ActivitiException("Unknown method used in expression: " + expressionText, mnfe);
    } catch (ELException ele) {
      throw new ActivitiException("Error while evaluating expression: " + expressionText, ele);
    } catch (Exception e) {
      throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
    }
  }

  public void setValue(Object value, VariableScope variableScope) {
    ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext(variableScope);
    try {
      ExpressionSetInvocation invocation = new ExpressionSetInvocation(valueExpression, elContext, value);
      Context.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(invocation);
    } catch (Exception e) {
      throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
    }
  }

  @Override
  public String toString() {
    if (valueExpression != null) {
      return valueExpression.getExpressionString();
    }
    return super.toString();
  }

  public String getExpressionText() {
    return expressionText;
  }
}

猜你喜欢

转载自blog.csdn.net/isyoungboy/article/details/81282699