Camunda学习笔记5-自动配置源码分析

流程引擎自动配置原理及源码分析

前言废话

其实很早就把文档写完了,五一出去玩前段时间又犯懒,直到今天才来了兴致,这篇主要记录分享自动配置和一些基础的参数配置过程,过段时间的下一篇还会分享任务流转相关的源码记录,希望能抛砖引玉对各位有用,趁热打铁吧!

1.为什么camunda会随程序启动自动配置

在springboot项目中引入camunda依赖非常方便,提前准备好数据库引入几个依赖就能完成自动配置和随项目自启动,和springboot的自动配置一样,camunda的配置工作也是通过几个注解的相互作用和特定的配置类完成的。我们跟踪源码看看具体的步骤是怎样的。首先找到下图的springboot-starter依赖包,这是自动配置的起点。

我们发现目录结构META-INF下有spring.factories文件,打开后发现里面有自动配置类CamundaBpmAutoConfiguration,而springboot的SPI机制在启动时会扫描META-INF/services/目录下所有接口或META-INF目录下spring.factories文件,进行自动配置的拓展。要注意的是这种写法需要写类的全限定名也就是 包路径+类名。

具体步骤如下:
1.根据启动类上的@SpringBootApplication注解找到@EnableAutoConfiguration注解,再找到@import的AutoConfigurationImportSelector类,这个类实现了DeferredImportSelector接口,这个接口又继承了ImportSelector接口,因此在AutoConfigurationImportSelector类重写了selectImports()方法。

2.selectImports()方法,该方法刚开始会先判断是否进行自动装配,随后会从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性,紧接着会调用getAutoConfigurationEntry()获取自动装配类的封装类,之后会调用getCandidateConfigurations()方法。

3.这个方法会调用SpringFactoriesLoader.loadFactoryNames()方法, 它会遍历读取META-INF/spring.factories文件里的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,进而得到需要装配的类。
这样就实现了随springboot项目启动而加载CamundaBpmAutoConfiguration类。

2.camunda自动配置做了哪些工作

自动配置类CamundaBpmAutoConfiguration里有许多声明了@Bean注解的方法,其中的ProcessEngineFactoryBean()方法创建返回了ProcessEngineFactoryBean类,而这个类使用工厂模式返回getObject()方法返回的ProcessEngineImpl类。

在用这个configuration配置类创建processEngine的过程中会进行初始化、校验启动配置是否正确、以及注入各种常用的service和常量,因为操作实在太多,下面挑几个简要概况一下所做的重要操作有哪些。

  1. init()初始化
    a.初始化上下文工厂并赋值绑定配置类,为后续new CommandContext()做准备



    b.初始化命令拦截器和拦截器的顺序,初始化命令执行器。可以看到在方法里创建了各个拦截器并手动指定链式连接的顺序,并保留了一个全局变量commandExecutorTxRequired,为了让后续Service和其他命令执行器都会先进入链式拦截器。

    c.初始化常用的Service,做的工作就是给所有service都绑定拦截器链条的头部执行器LogInteceptor,如果是repositoryService则额外设置部署语言默认配置UTF-8。

    d.初始化缓存工厂、初始化seesion工厂、初始化变量序列化器、校验历史数据清理线程数大小
  2. 将刚才init方法创建的service、Factory、Executor等绑定给流程引擎实例
  3. 执行3个命令执行器。
    a.第一个命令校验数据库连接,连接本地还是h2数据库,并且判断数据库更新属性需不需要启动前清空表,然后执行预先准备好的sql删除、更新或创建表.
    b.第二个命令建立数据库连接,判断配置文件的历史等级和数据库历史等级是否相同,不同则抛异常。
    c.第三个命令读取ACT_RU_JOB表,执行配置的定时任务,并根据historyCleanUp的配置判断是否执行清理历史数据的操作。

每个命令执行前都会按照拦截器顺序遍历拦截器,分别是LogInterceptor打印日志、ProcessApplicationContextInterceptor目的不清楚、SpringTransactionInterceptor开启spring事务、CommandContextInterceptor给命令执行器开启新的上下文以获取流程引擎参数,开启数据库连接,拿锁。

  1. 注册(其实就是put进一个map里)刚创建的流程引擎实例到processEngines
  2. 创建DbMetricsReporter数据库度量报告器并启动,不清楚作用
  3. 执行postProcessEngineBuild,设置filter和admin、group等属性
  4. 用repositoryService创建postProcessEngineBuild,扫描项目中带特定后缀的文件用input流的形式进行部署,这里是为什么启动会自动部署xml文件。
  1. 加载剩余的@Bean,自动配置类结束,项目启动。
总的来说,启动方法里比较重要的就是1.init()初始化和 7.input流加载系统目录下的xml流程图。init方法里用工厂模式和拦截器模式配置了包括流程命令模式的拦截器链、事务控制和数据库提交逻辑、每次调用拦截器链分配新的上下文对象、常用的各种service api、缓存工厂seesion工厂、流程变量类型序列化转换器等等一系列实用工具,最后初始化了一个processEngine对象供用户使用。
这种编程和业务实现习惯和平常大多数java开发工作都差别很大,有国内外的代码差异的原因更是因为这是一种DDD Domain Driven Design(领域驱动设计)模式的代码,业务代码强调无状态的操作,将一个大的任务拆分成多个细小领域,同时它们又共享某些核心的资源(例如流程上下文里的流程信息)。说到底还是为了代码复用减少耦合。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容