美文网首页activiti工作流程序员
activiti源码剖析--流程引擎ProcessEngine的

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

作者: 我有一只喵喵 | 来源:发表于2019-03-17 10:13 被阅读39次

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

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

    前言

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

    一、流程配置文件

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

    • 普通配置文件名称为activiti.cfg.xml
    <?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>
    
    • Spring配置文件名称为activiti-context.xml
    <?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;
        }
    

    该操作完成了以下操作:

    • 调用init方法初始化了各种属性值

      这里呢就是对一些诸如数据源、配置器、流程图片生成器、表达式管理器等一系列的初始化。

    • 实例化ProcessEngineImpl类

      那么这里就是实例化流程引擎的重头戏了。看代码实现

        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流程引擎管理对象了。

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

    相关文章

      网友评论

        本文标题:activiti源码剖析--流程引擎ProcessEngine的

        本文链接:https://www.haomeiwen.com/subject/kjdsmqtx.html