OSWorkflow代码结构,配置文件及初始化

转载 2007年10月12日 09:31:00
文档的版权属于 http://zstzah.blog.bokee.net
osworkflow 的代码结构
首先来看看它的包的静态结构,
workflow 包中我们发现了很多内容,光从名字上来看,就很一目了然。我将对最初常用的几个包进行阅读,后续在用到更多的功能时,补充该文档。 该文档原始地址
最早主要会提到的是 basic config loader 这三个包中的部分类,这三个包对于 osworkflow 的初始化非常重要。其中也会提到 spi 中的几个类,对于持久化操作的封装将使用这个包内的东西。
1  basic 这个包中有两个类, BasicWorkflow BasicWorkflowContext 。如下我们来看看这两个类的继承体系:下面首先是 workflow 控制流程对象的继承体系  
再来看看 BasicWorkflowContext 的继承体系:
 
 
 
 
这个包其实从名字上来看非常的明了,也就是我们从使用 osworkflow 的角度来看,一个流程实例的创建,我们可以使用的基本对象是 BasicWorkflow ,而我们同时也使用的 BasicWorkflowContext 这个对象来完成保存流程请求的用户的基本功能。
2  config 这个包完成的工作就像他的名字一样,基本的两个配置类在这个包中: DefaultConfiguration SpringConfiguration 。我们来看看这个包的基本结构:
 
DefaultConfiguration 这个类,完成了基本的配置文件的载入工作,包括 osworkflow.xml( 存放持久层配置以及流程工厂配置的文件 ) 以及 workflows.xml( 存放流程模型资源的配置文件 ) 的解析和映射。
我们来看看它的几个实例字段:
// 流程工厂类,通常被配置到 osworkflow.xml 文件中,在初始化的时候会去寻找是不是配置了别的工厂,如果配置了,将替换这个工厂的引用
    private AbstractWorkflowFactory factory = new URLWorkflowFactory();
 
// 持久化信息的 map ,从配置文件中读出来,存放到这个 map
    private Map persistenceArgs = new HashMap();
 
    // 完成持久化信息的各种工作的类全路径
private String persistenceClass;
 
// 这个引用本身是一个接口,它将在初始化发生的时候,赋予它的子类实现,这个接口在类中直接被实例化成 WorkflowStore 这接口的实现类。具体使用什么实现类将在配置文件中配置。
    private transient WorkflowStore store = null;
       // 这个是配置是否完成的标志字段,这个字段在 load 方法完成的时候,被设置为 true
    private boolean initialized;
 
SpringConfiguration 这个类为和 Spring 的整合提供了支持,目前还没有对 Spring 整合进行分析,在这里暂时不进行分析,将在以后补充。
3  loader 这个包,这个包中有大量的 Descriptor ,这些个描述符对象,记录了一个流程实例的步骤、动作、状态、名称等信息。由于这个类图过分庞大,因此不在这里出图例。这个类中也有一些关键的流程模型加载的工厂类,完成流程模型信息的初始化。我们在实际的应用中,只使用到了 XMLWorkflowFactory ,那么我们的流程配置文件自然也就使用了 xml 格式,在 AbstractWorkflow 中,大量的调用到了这个类的接口,来获取模型对象。这个类的详细分析,将放到以后的文档中。这里只要明白这个类是保存里流程模型对象的工厂,也就对模型进行一些操作,比如删除和保存一个流程模型。
4  spi 这个包里面的东西也很多,主要我们会提到的是记录流程实例状态的对象、持久化真正实现的方式。先来看看实例状态对象的类图:
SimpleWorkflowEntry 这个类,经常会用到,在流程启动和运行过程中,我们通常都使用这个类来标识流程实例的所对应的模型和实例状态。
5 、还有就是真正操作持久类的对象 Store
 
这里只把实际操作流程数据库的 jdbc 实现类图画出来。创建流程实例对象到数据库,操作流程实例相关的很多数据库数据。
 
 
osworkflow 的配置
在阅读 osworkflow 初始化之前有必要了解 osworkflwo 的一些基本配置。
首先,我们要知道 osworkflow 中需要配置的两个重要文件,这两个重要文件的配置是在使用 XMLWorkflowFactory 类来处理配置文件时一定要有的配置文件。
 
第一个 osworkflow.xml 文件,当然,你不可以随意指定这个文件的名称,而且你必须放到 classes 的根目录或者 META-INF 目录下,来看看这个部分的编码:
       // 使用默认文件名  
       if (is == null) {
            try {
                is = classLoader.getResourceAsStream("osworkflow.xml");
            } catch (Exception e) {
            }
        }
        if (is == null) {
            try {
                is = classLoader.getResourceAsStream("/osworkflow.xml");
            } catch (Exception e) {
            }
        }
        if (is == null) {
            try {
                is = classLoader.getResourceAsStream("META-INF/osworkflow.xml");
            } catch (Exception e) {
            }
        }
        if (is == null) {
            try {
                is = classLoader.getResourceAsStream("/META-INF/osworkflow.xml");
            } catch (Exception e) {
            }
        }
 
该代码来自 DefaultConfiguration 中的 load(url) 方法中,当然在这个代码所在的方法中, osworkflow.xml 文件是可以指定路径和文件名称的,主要是在调用 load 的上层 AstractWorkflow 中却没有传递任何文件路径和名称参数的接口,其实这个地方完全可以改成使用一个参数来确定文件的路径和名称的,传递 url AstractWorkflow 中去。
来看看这个文件的格式样例:
 
 
< osworkflow >
<!--
<persistence class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/>
-->
< persistence class = "com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore" >
   < property key = "datasource" value = "jdbc/osworkflow" />
   < property key = "entry.sequence"
value = " select isnull(max(ID),0)+1 from dbo.OS_WFENTRY" />
   < property key = "step.sequence"
value = "select sum(c1) + 1 from (select 1 as tb, count(*)
as c1    from os_currentstep union
select 2 as tb, count(*) as c1 from os_historystep) as TabelaFinal" />
</ persistence >
 
< factory class = "com.opensymphony.workflow.loader.XMLWorkflowFactory" >
        < property key = "resource" value = "workflows.xml" />
        < property key = "reload" value = "true" />
    </ factory >
</ osworkflow >
 
这个样例是使用 jdbc 来持久化流程实例的配置,
这里主要有两个关键结点:
<persistence > < factory >
 
1 <persistence > 元素中配置了一个 class 属性,在这里,它是一个持久化实现类的配置,那么里面的子元素都将针对这个 class 的配置进行特殊的配置,我这里是使用了 JDCBWorkflowStore 对象,在使用这个对象的前提下,只对三个 < property > 元素配置进行说明,一个是 key 属性是 entry.sequence step.sequence 的两个 < property > 元素,这两个元素主要是因为不同是数据库需要配置不同的实现方式,还有就是 datasource 的数据源元素。
以下分别对这三个元素进行配置说明:
key 值为 datasource < property > 元素:这个元素的 value 属性配置的是一个 jndi 的数据源,我们一般需要在特定的容器中配置特定的 jndi 数据源,以下是 tomcat 的例子:
 
<Context path="/osworkflow" docBase="osworkflow"
debug="99" reloadable="true" crossContext="true" verbosity="DEBUG">
<!-- debug level is set to paranoid, to know what is happening,
turn it off once you do not need it -->
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="OSWorkflow." suffix=".log" timestamp="true"/>
 
<Resource name= "jdbc/osworkflow"  auth="Container"
type="javax.sql.DataSource"/>
 
<ResourceParams name="jdbc/osworkflow">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>username</name>
<value>sa</value>
</parameter>
<parameter>
<name>password</name>
<value></value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>net.sourceforge.jtds.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:jtds:sqlserver://localhost:1433/osworkflow</value>
</parameter>
</ResourceParams>
</Context>
 
在这里,我不对数据源的配置进行细节说明,这里就是有一个很重要的地方需要指出:看这段数据源配置的最初, < Resource > 元素中 name 属性如果配置错误 ( 随意指定名称 ) ,那么程序在运行中将发生很多不可以理解的异常,系统会不停的打出数据源找不到的异常,然而我曾经花了很长的一段时间来寻找一个问题的原因,找遍了很多的代码也不能找到问题的原因,直到我后来去研读 PropertySet 开源项目的时候才发现,原来在这个开源架构的一个内部配置文件中,数据源已经被配置成 jdbc/DefaultDS ,因此上面这段配置最终会发生异常,因此如果不想让系统打印出数据源异常,这个数据源的配置务必配置成 jdbc/DefaultDS , 或者修改 PropertySet 的配置文件,在示例代码中,我故意把数据源的配置保持在错误的状态,读者可以运行这个示例,看看控制台出现了什么错误。不过在接下来的部分,马上就会改回正确配置,以进行下一步的研究。
 
key 值为 entry.sequence < property > 元素:在 osworkflow 中需要我们自己来配置,通常系统中会使用这个配置获取实例存放的数据 id 。这个值可以不配置,但它只提供了一种数据库的生成语句,它将使用 oracle 支持的一个 nextval (’ 序列号发生器名称 ’) ,去获取。
key 值为 step.sequence < property > 元素:同样,这里是用来获取当前所在的 step 的步骤 id 。同样,它也提供一个默认值,支持类似 oracle db 序列号发生器。
还有其他的很多配置,如果不使用自己特定的物理表格和特别的实现,可以不提供配置。如下来看看部分源代码:
 
entrySequence = getInitProperty(props, "entry.sequence", "SELECT nextVal(’seq_os_wfentry’)");
stepSequence = getInitProperty(props, "step.sequence", "SELECT nextVal(’seq_os_currentsteps’)");
entryTable = getInitProperty(props, "entry.table", "OS_WFENTRY");
entryId = getInitProperty(props, "entry.id", "ID");
entryName = getInitProperty(props, "entry.name", "NAME");
entryState = getInitProperty(props, "entry.state", "STATE");
historyTable = getInitProperty(props, "history.table", "OS_HISTORYSTEP");
currentTable = getInitProperty(props, "current.table", "OS_CURRENTSTEP");
currentPrevTable = getInitProperty(props, "currentPrev.table", "OS_CURRENTSTEP_PREV");
historyPrevTable = getInitProperty(props, "historyPrev.table", "OS_HISTORYSTEP_PREV");
stepId = getInitProperty(props, "step.id", "ID");
stepEntryId = getInitProperty(props, "step.entryId", "ENTRY_ID");
stepStepId = getInitProperty(props, "step.stepId", "STEP_ID");
stepActionId = getInitProperty(props, "step.actionId", "ACTION_ID");
stepOwner = getInitProperty(props, "step.owner", "OWNER");
 stepCaller = getInitProperty(props, "step.caller", "CALLER");
 stepStartDate = getInitProperty(props, "step.startDate", "START_DATE");
 stepFinishDate = getInitProperty(props, "step.finishDate", "FINISH_DATE");
 stepDueDate = getInitProperty(props, "step.dueDate", "DUE_DATE");
 stepStatus = getInitProperty(props, "step.status", "STATUS");
 stepPreviousId = getInitProperty(props, "step.previousId", "PREVIOUS_ID");
 
以上这段代码出现在 JDBCWorkflowStore init 方法中。它仅仅是读取了我们在 DefaultConfiguration 中解析配置文件后的 map persistenceArgs 后续我们会读这个类进行全面而细致的分析。
 
 
2 < factory > 这个元素主要是配置 WorkflowFactory 的地方,在这个工厂类中,我们完成了流程模型文件的基本信息的初始化,在实例项目中,使用了 XMLWorkflowFactory 来完成流程模型基本信息的初始化,以及对流程模型的获取删除等操作进行了代理。这个类也将在以后的章节中进行详细的分析。先来看看这个元素的配置:
这个元素的 class 属性指定了我们配置了完成模型基本信息初始化的工厂类。例子中使用的
XMLWorkflowFactory 类。
接下来的一个元素就是对模型资源文件的配置,这个资源文件存放了全部流程模型的路径等
信息。
  < property key = "resource" value = "workflows.xml" />
这个元素其实也可以不配置,如果不配置的话,默认就是 workflows.xml 而且默认路径就是
classes 下,或者是 META-INF 下,因此如果你不配置这个属性,请务必使用默认名称和默认路
径。
这个元素的配置意义,其实很明了,模型将在一定的条件下被重新解析和载入。这个元素同样也
是可以不配置的,默认情况下就是 false
   < property key = "reload" value = "true" />
 
 
 
第二个 workflows.xml 文件,这个文件就非常的简单了,只要把例子贴出来,应该不需要做什么解释了:
 
< workflows >
< workflow name = "simple" type = "resource" location = "oswk/test/config/simple.xml" />
</ workflows >
 
这个地方唯一要注意的就是: type 属性,该属性可以被配置为三种类型: url file resource 。这三种类型代表了三种文件的读取方式,来看看源代码:  
 
 
          if ("URL".equals(type)) {
                try {
                    url = new URL(location);
 
                    File file = new File(url.getFile());
 
                    if (file.exists()) {
                        lastModified = file.lastModified();
                    }
                } catch (Exception ex) {
                }
            } else if ("file".equals(type)) {
                try {
                    File file = new File(location);
                    url = file.toURL();
                    lastModified = file.lastModified();
                } catch (Exception ex) {
                }
            } else {
url=Thread.currentThread().getContextClassLoader().getResource(location);
            }
 
 
最后 一个文件就是流程模型文件了
workflow 模型文件。
首先我们来熟悉一下 workflow 的基本概念。
简单的讲, workflow 就是一个自动化流程引擎,我们把企业业务流程抽象出来,让 workflow engine 来统一管理和执行、监控。按照 WFMC 的定义:
全部或者部分,由计算机支持或自动处理的业务过程。
在不使用 workflow engine 的传统企业应用系统中,我们可能会散乱和抽象一些直接编写流程控制代码在业务系统中,这样的一种模式基本上是目前应用系统的主流模式。也许良好的体系架构足够的优秀,它抽象了很高层的逻辑来适应企业应用在未来的变化。
在我们面对一个应用系统进行较高层的设计时,总是在考虑如何才能将系统各个层面的依赖尽量的降低。从企业业务的角度来看,我们可以抽象出两个比较高层的层面:一是流程,二是活动。那么流程,就像是一条或者多条交错贯穿的线索,它连接着业务中各个结点的变化,线索的分支、合并等。而活动就是各个结点上发生的事情,这些发生的事情决定了线索的走向和状态。
系统架构设计的其中一个很重要的目的就是将系统中的层面尽可能的划分清晰,尽可能的松散耦合。那么我们如何才能把流程和活动清晰的划分呢?如何让流程牵引活动的执行呢?而活动对于流程来说是透明的,流程永远不知道在它上面的活动做了什么,它只需要流程得以继续流转的信息。同样,活动也并不知道流程的存在,它只提供活动执行的结果和其他信息。
那么,现在就很明确了, workflow 就是这样一个东西,它定义了一个流程,并控制了整个流程的运行,安排活动在流程内部被呼叫,以及被定义了执行的顺序。
 
因此从 workflow 的视角来看,一个完整的流程就是一个实体,而这个实体的开始、运行、结束都被定义在 workflow 管理的一个规则模型中。接下来,我要分析的就是 oswolkflow 的这个模型定义,这里要表现的模型文件格式是开放的 xml 文件格式。
这个模型文件的的结构非常的复杂,里面包含了比较多的控制逻辑。来完成流程的运作。
如下是一个空的文件样式:
 
<? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN"
"http://www.opensymphony.com/osworkflow/workflow_2_7.dtd" >
< workflow >
   < initial-actions >
   </ initial-actions >
   < steps >
     < step name = "" id = "1" >
     </ step >
     < step name = "" id = "4" >
     </ step >
     < step name = "" id = "5" >
     </ step >
   </ steps >
</ workflow >
这个样式提供了最基本的要素,我们通过 initail-action 来启动一个流程实例,然后在 step 里面定义活动来完成各个工作,查看 dtd 的定义
  
<!ELEMENT workflow (meta*, registers?, trigger-functions?, initial-actions, global-actions?, common-actions?, steps, splits?, joins?)>
 
根元素 workflow 中可以定义的子元素很多
1 registers 元素的作用是在外部调用流程实例的执行一些动作的时候, registers 下的动作都将被调用,这个地方非常适合存放流程日志,来记录流程调用轨迹。可选,且只能有一个;
2 global-actions 元素的作用其实从字面也可以很理解,就是一些全局的 actions ,它的存在是为了一些任何步骤都可能被执行的动作,它被放到了 workflow 根元素下面,在流程进入到任何 step 的时候,都可以执行这个元素下的 actions 。可选,且只能有一个;
3 trigger - functions 元素的作用,这个元素是一个需要使用 api 执行的 functions 适合系统外部被调用。可选,且只能有一个;
4 initial - actions 元素的作用就更加的明确了,它就是一个流程实例被启动的时候需要执行的元素。必须
5 common-actions 元素的作用,这个元素也被定义在全局的范围内,它的下面可以定义 actions ,被 step 内部的 action id 的方式引用。可选,且只能有一个;
6 steps 元素的作用基本算是最核心的元素了,每个流程的跳转都以这个元素为依据,这个里面我们会配置很多的 actions 来完各种动作。必须
7 splits 我们在这个元素中配置需要并行执行的 steps ,完成了并行流程。可选,且只能有一个;
8 joins 这个元素就是一个汇集了,我们可以把 step 中执行的 action 连接到这个元素,来完成多个 actions 执行完的其他处理,比如判断执行情况,来处理下一个 step 中的 action 。可选,且只能有一个。
 
osworkflow 初始化分析
本文档内容完全取之我对 osworkflow2.7.0 源代码的理解,因此在阅读的时候请参照源代码。文档的撰写是以配置 XMLWorkflowFactory 上,使用 jdbc 持久化的基础上整理。如果你不熟悉 osworkflow 代码结构,在阅读该文档前请务必先阅读 <oswrkflow 代码结构 > 。文档的撰写是在我从来没有接触 osworkflow 的前提下,难免有错误,请指正。
1  osworkflow 的初始化:
通常 osworkflow 将在流程第一次实例化的时候来初始化流程模型等资源,当然也可以进行扩展,让容器在启动的时候来初始化基本的信息。
AbstractWorkflow 中的 initialize 方法中有这么几行代码:
 
        WorkflowDescriptor wf = getConfiguration().getWorkflow(workflowName);
        WorkflowStore store = getPersistence();
        WorkflowEntry entry = store.createEntry(workflowName);
 
 WorkflowDescriptor wf = getConfiguration().getWorkflow(workflowName);
// 这行代码其实包含的内容很多,最初的 getConfiguration() ,获取了 Configuration 对象,在 AbstractWorkflow 中返回的是 DefaultConfiguration ,引擎将在系统首次访问流程数据的时候初始化持久信息,以及流程工厂对象。它负责全部的流程 静态 信息,这些静态信息将被插入到一个 map 中,包括装载流程配置信息,设置 workflow descriptor factory, 也对 workflow descriptor factory 的调用进行了代理。
// getWorkflow(workflowName) 中,使用了 Configuration 的具体实现类获取了指定名称对应的模型静态对象,事实上是一个 WorkflowConfig 对象,通常情况下这个对象是 XMLWorkflowFactory inner class XMLWorkflowFactory 会依据配置文件中的流程模型列表生成的模型对象 map 中获取 . WorkflowConfig 这个内部类记录了一个模型文件的静态信息,包括最后修改时间,位置,路径,以及模型文件对应的逻辑类 WorkflowDescriptor ,这个字段,在 WorkflowConfig 最初被创建的时候并不进行初始,通常会在第一次获取一个模型对应的实例时被初始化,如果在流程工厂结点中设置了 reload true 的参数,那么在这个流程模版被修改的时候将再一次被重新初始化。这个 XMLWorkflowFactory 使用的是典型的 flyweight( 享元 ) 模式,这个模式无疑会提高系统效率。
WorkflowStore store = getPersistence(); // 获取流程数据的操作类,在实际的使用中它通常是一个数据库操作的封装, ejb hibernate, 或者 jdbc
WorkflowEntry entry = store.createEntry(workflowName);// 这里就是依据模型名称,来激活一个流程实例 , 在实际的系统中,我们通常是将一条数据插入到数据库,代表一个被激活的流程
 
我们再来看看这个 initialize 方法的三个参数:
workflowName (String) initialAction(int) inputs(Map)`
 
workflowName: 无疑是一个流程模型的名称,这个事实上是配置文件中配置的 xml 模型文件的别名,如下面代码中的 simple
<workflows>
    <workflow name="simple" type="resource" location="oswk/test/config/simple.xml"/>
</workflows>
 
 
 
 
 
 

initialAction: xml 模型文件中的 action 元素的 id 属性 . 光从字面上理解,通常是 <initial-actions> 元素中的一个 <action> 元素是 id 属性
inputs: 可以利用这个 map 来传递其他的一些参数信息,完成更丰富的流程控制。
 
 
再往下走,我们会看见这么一段代码:
        populateTransientMap(entry,               // 一个流程实例
                      transientVars,
                      wf.getRegisters(),
                      new Integer(initialAction), // 用来初始化流程的 action 编号
                      Collections.EMPTY_LIST);  
这段代码在一个实例运行的时候起到了非常重要的作用,在一个流程实例状态和数据发生改变的时候,这段代码就会被调用。我们可以在 getAvailableActions getSecurityPermissions canInitialize doAction executeTriggerFunction initialize getAvailableAutoActions 这些方法中看到它的存在。
看看这个方法体的参数: entry ,这个参数是模型的实例的信息对象,这个对象记录了一个模型实例的基本信息,包括模型名称、是否初始化、目前的状态、代表这个实例的标识。 JDBCWorkflowStore 中调用的是 SimpleWorkflowEntry ,那么标识就是数据库中的唯一 ID transientVars ,这个参数其实是一个容器,它存放了全部和流程实例相关的一些数据,包括用户传递的参数 ( 如果你在代码中传递了 initialize 方法的第三个参数 ) 、调用者信息、模型实例对象、持久化封装对象、模型信息对象 ( 将模型信息的文件格式变成结构对象 ) 、存在的 actionId 、所在的 currentSteps 等等。我们来看这段代码:
        if (inputs != null) {
            transientVars.putAll(inputs);
        }
这段代码的含义非常的明了, initialize 方法中 inputs 参数是可选的,如果传递了,这些参数将被保存到 transientVars
2  DefaultConfiguration 分析:我们再来看看这个类在系统中的类图结构
 
 
 很显然,这个类实现了 Configuration 接口,这个接口定义的方法,是一些完成获取流程模型的基本方法。如下我们详细解释关键接口的用处
1 isInitalized() :这个接口很明显,它标记 osworkflow 配置文件是否已经初始化的接口。系统会在实例化一个流程的时候去调用它,以确认已经初始化 .
2 getPersistence() setPersistence() 这两个接口是对持久化类的类路径进行设定和获取。这个类被配置在 osworkflow.xml 文件中的 <persistence> 元素的 class 属性中。
3 getPersistenceArgs() 这个接口是获取了持久化信息的 map ,从配置文件中读出来,存放到这个 map 中,这个 map 的信息是从 <persistence> 元素的子元素中读取的,一堆
<property key="" value=""/> 元素
4 getWorkflowStore() 这个接口,获取被实例化的持久化类对象。这个对象完成了流程模型实例的持久化操作。
5 load() 这个方法将 osworkflow.xml 文件加载进来,其中将模型信息进行对象化,存放在内存。然后让一个工厂类来负责管理它们。
6 removeWorkflow() saveWorkflow() 接口,其中 removeWorkflow() 方法在
XMLWorkflowFactory 中,这个方法是无效的,没有实现,调用它的时候会抛出异常。 saveWorkflow() 方法在 XMLWorkflowFactory 中的实现是也对一个已经存在的流程进行修改,然后保存的过程。现在我还没有发现 osworkflow 有实现了对新建流程的保存。
3  XMLWorkflowFactory 分析:我们也来看看这个类在系统中的类图结构:
 
首先,在超类中实现了两个方法
    protected Properties properties = new Properties();
    /**
     * Get the configuration properties of this factory
     */
    public Properties getProperties() {
        return properties;
    }
    public final void init(Properties p) {
        this.properties = p;
    }
 
这个两个方法其实很简单,在 DefaultConfiguration load() 方法中会调用其中的 init() 来完成持久化信息配置的 properties 的传递。
先看看 getWorkflow(String workflowname) 这个接口,这个接口在 XMLWorkflowFactory 中实现的是首先获取一个内部类,这个内部类中保存了一个 descriptor 对象,在最初的时候,已经在 DefaultConfiguration 调用了 initDone() 方法完成了这个工作 ( 参见本文挡的 1 osworkflow 的初始化 ) 。在这里,这个 descriptor 对象就真正的被实例化了,之所以这样设计,首先是为了提高效率,同时也为流程模型的修改热载入提供了支持。
 

ASP.NET就业实例视频教程(4)三层架构——让代码结构更清晰

-
  • 1970年01月01日 08:00

osworkflow代码结构,配置文件及初始化

   文档的版权属于http://zstzah.blog.bokee.net一 osworkflow的代码结构首先来看看它的包的静态结构,在workflow包中我们发现了很多内容,光从名字上来看,就很...
  • liumm1983
  • liumm1983
  • 2007-03-28 10:29:00
  • 2295

OSWorkFlow流程配置文件详解

AbstractWorkflow>> osworkflow中有关工作流流转的所有核心代码都在AbstractWorkflow中,BasicWorkflow就是派生自它,不过这个BasicWorkfl...
  • lifuxiangcaohui
  • lifuxiangcaohui
  • 2014-09-04 11:32:00
  • 3278

osworkflow的流程定义文件的type怎么配置?

我们对下面的配置很熟悉了:    有朋友问这里的type应该怎么配置?有哪些type?我们看看代码就明白了:XMLWorkflowFactory.java:if ("URL".equals(type)...
  • hongbo781202
  • hongbo781202
  • 2004-11-22 18:28:00
  • 2526

学会利用“配置文件”优化我们的代码结构

之前我们讲过某些时候可以利用数组来代替if/else来优化代码, 在本文中, 我们再次来复习一下, 顺便学学利用配置文件来优化代码结构, 好, 开始吧。        假设有这样一个场景: 某系统...
  • stpeace
  • stpeace
  • 2015-03-13 23:40:35
  • 3225

osworkflow的代码结构分析

osworkflow是一个轻量级工作流引擎,代码结构非常简单明了,具体如下:1)com.opensymphony.workflow  工作流的代码接口2)com.opensymphony.work...
  • techcrunch
  • techcrunch
  • 2008-04-09 01:39:00
  • 217

osworkflow的代码结构分析

osworkflow是一个轻量级工作流引擎,代码结构非常简单明了,具体如下:1)com.opensymphony.workflow  工作流的代码接口2)com.opensymphony.workfl...
  • hongbo781202
  • hongbo781202
  • 2004-11-21 21:09:00
  • 3966

osworkflow入门篇

所有相关的osworkflow的文档大家可以到http://wiki.opensymphony.com/space/OSWorkflow处得到,我这里就我的理解,以及对osworkflow文档阅读的心...
  • yun15291li
  • yun15291li
  • 2005-07-18 02:55:00
  • 3079

转载&gt;《OSWorkFlow》代码结构

该文档的版权属于http://zstzah.blog.bokee.net首先来看看它的包的静态结构,在workflow包中我们发现了很多内容,光从名字上来看,就很一目了然。我将对最初常用的几个包进行阅...
  • wn_1985
  • wn_1985
  • 2008-08-05 11:15:00
  • 168

用OSWorkFlow和JBPM开发工作流异同

一、用OSWorkFlow和JBPM开发工作流,首先要做的都是编写工作流描述文件,在此基础上再进一步做相关的配置和调用。二、编写流程描述文件方式1、  JBPM是通过图形化的编辑工具(JBPM自带的E...
  • victor16345
  • victor16345
  • 2010-05-21 17:10:00
  • 13322
收藏助手
不良信息举报
您举报文章:OSWorkflow代码结构,配置文件及初始化
举报原因:
原因补充:

(最多只允许输入30个字)