jbpm源码阅读之四-JBPM解析配置文件方法-讲解


JBPM解析配置文件方法-讲解

这一次阅读,我们来研究一下上一节遗留下来的问题.JBPM是如何实现解析配置文件的.具体的方法在ConfigurationParser类中,我把方法分成了几部分来讲述,接下来我们一步步来分析.

 

public Object parseDocument(Document document, Parse parse) {
    // if the default environment factory was already set in the parse
	//将先前压进Stack的ConfigurationImpl.class找出来.
    ConfigurationImpl configuration = parse.contextStackFind(ConfigurationImpl.class);
    
    Element documentElement = document.getDocumentElement();
    if (documentElement != null) {
      // this code will be called for the original jbpm.cfg.xml document as 
      // well as for the imported documents.  only one of those can specify
      // a spring-cfg.  for sure no 2 config files can specify different jndi-names
      String spring = XmlUtil.attribute(documentElement, "spring");//是否支持Spring
      if ("enabled".equals(spring)) {
        configuration.springEnabled();
      }
  
      // this code will be called for the original jbpm.cfg.xml document as 
      // well as for the imported documents.  only one of those can specify
      // a jndi-name.  for sure no 2 config files can specify different jndi-names
      String jndiName = XmlUtil.attribute(documentElement, "jndi-name");
      if (jndiName!=null) {
        if ( (configuration.getJndiName()!=null)
             && (!jndiName.equals(configuration.getJndiName()))
           ) {
          parse.addProblem("duplicate jndi name specification: "+jndiName+" != "+configuration.getJndiName());
        } else {
          configuration.jndi(jndiName);
        }
      }
  

 

 

  • 首先,parseDocument方法将先前压进Stack的ConfigurationImpl.class找出来.
  • 接着获取document的根节点.
  • 然后,对属性进行判断:是否支持Spring和判断jndi-name是否有重复.

 

 

//递归解析import,所有有相互引用的,使用递归解析是最好的处理方式. for (Element importElement : XmlUtil.elements(documentElement, "import")) {//解析import if (importElement.hasAttribute("resource")) { String resource = importElement.getAttribute("resource"); Parse importParse = createParse() .setResource(resource) .contextStackPush(configuration) .propagateContexMap(parse) .execute(); parse.addProblems(importParse.getProblems()); } }  

    这一部分代码似曾相识,我们回忆一下在ConfigurationImpl类中,也有类似的这段代码.功能也是一样的,解析配置文件.但这里是递归解析import,在所有有相互引用的解析中,使用递归解析是最好的处理方式.

    接下来,我们逐行的看下代码,

 

  • 首先获得属性resource中的资源名称.
  • 然后创建一个解析对象,并将解析器放入其中(从Parse类中,我们可以理解到createParse()方法,是ConfigurationParser解析器放入解析对象Parse中,而不是Parser.).
  • setResource()很好理解,是设置配置文件资源.
  • contextStackPush(),则是将配置类放入堆栈中.
  • propagateContexMap(parse),传播parse中使用的ContectMap,合并两个parse的ContextMap内容且使用同一个ContextMap.(这里我们怎么理解呢?可以研究下propagateContexMap ()方法的实现.)

    注意,下面这部分代码在Parse类中.

public Parse propagateContexMap(Parse parse) {
    if (parse.contextMap==null) {
      parse.contextMap = new HashMap<String, Object>();
    }
    if (this.contextMap!=null) {
      parse.contextMap.putAll(this.contextMap);//将this.contextMap放到parse.contextMap.
    }
    this.contextMap = parse.contextMap;//让this使用parse的contextMap.
    return this;
  }

 

  • 最后就是execute()了,跟前文讲解ConfigurationImpl类中的解析方法一样.

 

 

Element processEngineElement = XmlUtil.element(documentElement, "process-engine-context"); if (processEngineElement != null) { WireDefinition processEngineContextDefinition = configuration.getProcessEngineWireContext().getWireDefinition(); parse.contextStackPush(processEngineContextDefinition); try { processEngineContextParser.parseDocumentElement(processEngineElement, parse); } finally { parse.contextStackPop(); } }  

 

 

Element txCtxElement = XmlUtil.element(documentElement, "transaction-context"); if (txCtxElement != null) { WireDefinition transactionContextDefinition = configuration.getTransactionWireDefinition(); parse.contextStackPush(transactionContextDefinition); try { transactionContextParser.parseDocumentElement(txCtxElement, parse); } finally { parse.contextStackPop(); } } }

    上面两部分是解析实质内容process-engine-context和transaction-context.

 

  总结

    在这一次阅读中,我们可以发现,一般情况下一个配置文件的结构是怎么样的,可以从parseDocument()方法的解析过程看出.

 

  • 首先是解析一些属性.
  • 然后是递归解析import.
  • 接着是ProcessEngine上下文和事务上下文配置.
   是否如此呢?我们可以打开一个JBPM配置文件看看便得到满意的结果.下面的配置文件除了属性部分是没有的,import,流程引擎上下文和事务上下文配置都是有的.如此看来,我们了解了JBPM是怎么解析配置文件的.
<?xml version="1.0" encoding="UTF-8"?>

<jbpm-configuration>

  <import resource="jbpm.default.scriptmanager.xml" />
  <import resource="jbpm.mail.templates.xml" />

  <process-engine-context>
  
    <repository-service />
    <repository-cache />
    <execution-service />
    <history-service />
    <management-service />
    <identity-service />
    <task-service />

    <object class="org.jbpm.pvm.internal.id.DatabaseDbidGenerator">
      <field name="commandService"><ref object="newTxRequiredCommandService" /></field>
    </object>

    <object class="org.jbpm.pvm.internal.id.DatabaseIdComposer" init="eager" />
    
    <object class="org.jbpm.pvm.internal.el.JbpmElFactoryImpl" />

    <types resource="jbpm.variable.types.xml" />

    <address-resolver />
 
  </process-engine-context>

  <transaction-context>
    <repository-session />
    <db-session />
    
    <message-session />
    <timer-session />
    
    <history-sessions>
      <object class="org.jbpm.pvm.internal.history.HistorySessionImpl" />
    </history-sessions>
    
    <mail-session>
      <mail-server>
        <session-properties resource="jbpm.mail.properties" />
      </mail-server>
    </mail-session>

  </transaction-context>

</jbpm-configuration>
 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值