activiti工作流程序员

activiti源码剖析--流程引擎ProcessEngine的

2019-03-17  本文已影响39人  我有一只喵喵

感谢冀正,张志祥前辈《Activiti权威指南》

activiti源码剖析--流程引擎ProcessEngine的获取

前言

本篇文章通过源码进行分析ProcessEngine是如何被创建出来,在学习activiti的同时,通过源码进行分析以对activiti流程引擎进行更深层次的理解深入。

一、流程配置文件

Acticiti配置文件的风格使用了Spring中的文件配置方式,这样有什么好处呢?那当然从Spring的特性IOC说起,依赖注入,控制反转,这里就不再多说,选取这样的配置方式也说明了,Activiti在设计之时就考虑到了与spring的融合。activiti的配置文件类型分为 普通配置 和Spring配置(这里说明一下,activiti的配置文件方式采用Spring方式,但是activiti可以集成Spring开发,也可以不集成,所以后者的Spring配置方式其实也就是集成Spring进行开发)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">
       
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="1234" />
        <property name="databaseSchemaUpdate" value="true" />
    </bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_activiti"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
    </bean>
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置注解方式配置事务-->
    <tx:annotation-driven  proxy-target-class="true" transaction-manager="transactionManager"/>
    <!--定义基于Spring的引擎配置对象BEAN-->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="deploymentResources" value="classpath:userAndGroupTest.bpmn20.xml"/>
        <!--<property name="jobExecutorActivate" value="false"/>-->
    </bean>

    <!--配置引擎工厂对象BEAN-->
    <bean id="processEngineFactory" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>

    <!--使用spring提供的工厂方式获取actititi7个service接口对象-->
    <bean id="repositoryService" factory-bean="processEngineFactory" factory-method="getRepositoryService"/>
   ....7大服务
</beans>

二、构造流程引擎实例对象

获取流程引擎实例对象代码如下

        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        //这里也可以通过自定义流程引擎名称获取
        //ProcessEngines.getProcessEngine(String processEngineName)

        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        assert repositoryService !=null;

ProcessEngines:该类负责管理所有的流程引擎ProcessEngine集合,并负责流程引擎实例对象的注册、获取、注销等操作。

只需要ProcessEngines.getDefaultProcessEngine();一句话即可获取到我们的重要角色:processEngine,那么它是怎么被获取到的呢?接下来围绕这一话题进行源码剖析。

ProcessEngines.java源码

    public static ProcessEngine getDefaultProcessEngine() {
        return getProcessEngine("default");
    }

相信从这里也可看出来,在通过ProcessEngines获取流程引擎的时候,不管使用默认的方式还是通过指定流程引擎名称,其实都是调用的ProcessEngine(processEngineName)方法获取

    public static ProcessEngine getProcessEngine(String processEngineName) {
        if (!isInitialized()) {
            init();
        }
        return (ProcessEngine)processEngines.get(processEngineName);
    }

在获取流程引擎的前提要先进行初始化。如果已经完成初始化,那么返回指定名称的流程引擎对象。从这里也可以看出Activiti支持多个流程引擎实例对象一起运行,通过流程引擎名称进行区分。

protected static Map<String, ProcessEngine> processEngines = new HashMap();

在这里processEngines为MAP结构,key为流程引擎名称,value为流程引擎实例对象。

接下来看看Activiti是如何做初始化准备工作的

    public static synchronized void init() {
        
        if (!isInitialized()) {
            if (processEngines == null) {
                processEngines = new HashMap();
            }

            ClassLoader classLoader = ReflectUtil.getClassLoader();
            Enumeration resources = null;

            try {
                resources = classLoader.getResources("activiti.cfg.xml");
            } catch (IOException var6) {
                throw new ActivitiIllegalArgumentException("problem retrieving activiti.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), var6);
            }

            HashSet configUrls = new HashSet();

            while(resources.hasMoreElements()) {
                configUrls.add(resources.nextElement());
            }

            Iterator iterator = configUrls.iterator();

            while(iterator.hasNext()) {
                URL resource = (URL)iterator.next();
                log.info("Initializing process engine using configuration '{}'", resource.toString());
                initProcessEngineFromResource(resource);
            }

            try {
                resources = classLoader.getResources("activiti-context.xml");
            } catch (IOException var5) {
                throw new ActivitiIllegalArgumentException("problem retrieving activiti-context.xml resources on the classpath: " + System.getProperty("java.class.path"), var5);
            }

            while(resources.hasMoreElements()) {
                URL resource = (URL)resources.nextElement();
                log.info("Initializing process engine using Spring configuration '{}'", resource.toString());
                initProcessEngineFromSpringResource(resource);
            }

            setInitialized(true);
        } else {
            log.info("Process engines already initialized");
        }

    }

首先再次判断确认流程引擎是否已经被初始化。 接下的工作就是定位activiti配置文件啦,(在这里可以看到是从根路径中加载配置文件,为什么的话,可以从这里补充补充知识getClass().getResource()和classLoader.getResource())这里也可以看出activiti配置文件的名称啦。

普通配置文件(activiti.cfg.xml)通过initProcessEngineFromResource(resource);进行初始化加载,集成spring配置文件通过initProcessEngineFromSpringResource(resource);进行初始化加载。

2.1、初始化流程引擎之普通配置文件

再进入initProcessEngineFromResource(resource)首先是做了大量的准备工作,准备工作其实也就是清除已经存在同名称的流程引擎信息,之后调用buildProcessEngine(resourceUrl)构造流程引擎实例对象,然后放入新的流程引擎信息相关信息。

    private static ProcessEngine buildProcessEngine(URL resource) {
        InputStream inputStream = null;

        ProcessEngine var3;
        try {
            inputStream = resource.openStream();
            ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
            var3 = processEngineConfiguration.buildProcessEngine();
        } catch (IOException var7) {
            throw new ActivitiIllegalArgumentException("couldn't open resource stream: " + var7.getMessage(), var7);
        } finally {
            IoUtil.closeSilently(inputStream);
        }

        return var3;
    }

buildProcessEngine(resourceUrl) 中进入ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);核心代码

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream) {
        return createProcessEngineConfigurationFromInputStream(inputStream, "processEngineConfiguration");
    }

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName) {
        return BeansConfigurationHelper.parseProcessEngineConfigurationFromInputStream(inputStream, beanName);
    }

从以上代码可以看出是在获取通过spring容器管理的id为processEngineConfiguration的bean对象。即org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration(配置文件中配置)。之后Spring会解析xml配置文件实例化org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration对象

ProcessEngineConfigurationImpl类结构.png

在实例化org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration的同时,也会对其父类进行初始化,点击ProcessEngineConfigurationImpl类进入查看

    protected RepositoryService repositoryService = new RepositoryServiceImpl();
    protected RuntimeService runtimeService = new RuntimeServiceImpl();
    protected HistoryService historyService = new HistoryServiceImpl(this);
    protected IdentityService identityService = new IdentityServiceImpl();
    protected TaskService taskService = new TaskServiceImpl(this);
    protected FormService formService = new FormServiceImpl();
    protected ManagementService managementService = new ManagementServiceImpl();
    protected DynamicBpmnService dynamicBpmnService = new DynamicBpmnServiceImpl(this);

也就是在进行各种服务类对象的初始化。在这里完成了对流程引擎配置对象的初始化,注意上述buildProcessEngine(resourceUrl)中在初始化流程引擎配置对象之后,通过流程引擎配置对象来build processEngine,var3 = processEngineConfiguration.buildProcessEngine();这里方法的实现是在各种配置类的父类(ProcessEngineConfigurationImpl)中进行了实现

ProcessEngineConfigurationImpl.java

   public ProcessEngine buildProcessEngine() {
        this.init();
        ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
        if (this.isActiviti5CompatibilityEnabled && this.activiti5CompatibilityHandler != null) {
            Context.setProcessEngineConfiguration(processEngine.getProcessEngineConfiguration());
            this.activiti5CompatibilityHandler.getRawProcessEngine();
        }

        this.postProcessEngineInitialisation();
        return processEngine;
    }

该操作完成了以下操作:

    public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
        this.processEngineConfiguration = processEngineConfiguration;
        this.name = processEngineConfiguration.getProcessEngineName();
        this.repositoryService = processEngineConfiguration.getRepositoryService();
       ....这里就是在填充7大服务对象
        this.dynamicBpmnService = processEngineConfiguration.getDynamicBpmnService();
        this.asyncExecutor = processEngineConfiguration.getAsyncExecutor();//异步作业执行器
        this.commandExecutor = processEngineConfiguration.getCommandExecutor();//命令执行器
        this.sessionFactories = processEngineConfiguration.getSessionFactories();
        this.transactionContextFactory = processEngineConfiguration.getTransactionContextFactory();//事务
       ...
        if (processEngineConfiguration.isUsingRelationalDatabase() && processEngineConfiguration.getDatabaseSchemaUpdate() != null) {
            this.commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaOperationsProcessEngineBuild());//这里就是通过databaseSchemaUpdate值进行数据库生成策略
        }
       ...

        ProcessEngines.registerProcessEngine(this);//注册流程引擎
        if (this.asyncExecutor != null && this.asyncExecutor.isAutoActivate()) {
            this.asyncExecutor.start();//启动异步执行器
        }

        if (processEngineConfiguration.getProcessEngineLifecycleListener() != null) {
            processEngineConfiguration.getProcessEngineLifecycleListener().onProcessEngineBuilt(this);//触发流程引擎生命周期监听器
        }
 processEngineConfiguration.getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createGlobalEvent(ActivitiEventType.ENGINE_CREATED));
    }

上述代码看出,在对一些属性装配完成之后,操作引擎表(具体策略以及如何生成看这里activiti源码剖析之操作引擎表)之后注册流程引擎,也就是将processEngineImpl实例对象注册进ProssEngines中,到这里想必已经明白了文章开始代码,ProcessEngines是如何获取到processEngine的。

到这里,大致已经明白是ProcessEngine流程引擎是如何初始化并且注册进processEngines流程引擎管理对象了。

希望大家指正,内容也会随着学习深入与实践的过程中进行改善

上一篇下一篇

猜你喜欢

热点阅读