activiti7源码分析之引擎初始化与Bean注入
在之前的一篇文章中,介绍了Soringboot2
与activiti7
整合,本文我们看下整合后的activiti7
是如何初始化的,以及相关Bean
如何注入。
配置和创建工作流引擎
首先第一个问题,activiti7
的初始化工作是怎么启动呢?我得从盘古开天辟地说起,顺便复习下Springboot
相关知识。
Springboot
的main函数上有个注解@SpringBootApplication
,我们看下这个注解的的实现,只看关键部分:
在这段代码中有一个关键的注解@EnableAutoConfiguration
,这个注解的作用是顾名思义的就是允许自动配置,怎么实现呢,继续看@EnableAutoConfiguration
的源码:
在这段代码中,@Import({AutoConfigurationImportSelector.class})
的作用是将AutoConfigurationImportSelector
这个类注册为Bean交给容器管理。这个类里面有个关键方法public String[] selectImports(AnnotationMetadata annotationMetadata)
,作用是扫描所有包(包含依赖jar包)中的META-INF/spring.factories
文件,把其中key为"...EnableAutoConfiguration"对应的value里的类都加载为Bean。
看下activiti-spring-boot-starter
这个包中spring.factories
文件的内容:
所以,这个文件里面的三个类都被加载为Bean。即EndpointAutoConfiguration
,ProcessEngineAutoConfiguration
,ActivitiMethodSecurityAutoConfiguration
这三个。这就是Springboot
的自动配置原理。总结起来就是@EnableAutoConfiguration
会自动扫描所有包下面的META-INF/spring.factories
文件,将其中key以EnableAutoConfiguration
结尾的对应的value的类全部加载为Bean。这就是SPI机制,与JDK中的SPI和DUBBO的SPI类似,但是具体实现方法不一样。关于SPI我之后会详细讲解。
我们关注ProcessEngineAutoConfiguration
这个Bean,其余两个以后再解释。
看下ProcessEngineAutoConfiguration
这个类部分的源码:
这个类主要作用的就是流程引擎的配置,注解@EnableConfigurationProperties({ActivitiProperties.class, AsyncExecutorProperties.class})
会将在properties
中的配置属性映射到对应的类的属性中去。例如常用的在application-dev.properties
配置的database-schema-update
,history-level
,db-history-used
等属性就是在这里被映射到类ActivitiProperties
中去的,然后在SpringProcessEngineConfiguration springProcessEngineConfiguration()
方法中添加到引擎配置类中的。
ProcessEngineAutoConfiguration
中会注册很多Bean,其中有个比较重要:
SpringProcessEngineConfiguration
这个Bean主要负责流程引擎的配置,将数据源和Springboot
配置文件中配置的activiti7
的相关属性配置到引擎中去。这个Bean被注解@ConditionalOnMissingBean
修饰,意思是只有在容器中不存在SpringProcessEngineConfiguration
的情况下这个Bean才会被注册,因此如果要自定义自己的引擎配置,重新定义一个SpringProcessEngineConfiguration
类型的Bean即可。
ProcessEngineAutoConfiguration
继承了AbstractProcessEngineAutoConfiguration
,这个抽象类里面定义了几个比较重要的Bean:
ProcessEngineFactoryBean
这个Bean的主要作用产生ProcessEngine
Bean,可以理解为是产生Bean的Bean,比较拗口。这个Bean实现了FactoryBean
接口,FactoryBean
接口是spring里面一个接口,与它长得比较类似的事BeanFactory
,它们作用完全不一样。FactoryBean
是一个工厂Bean,可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。BeanFactory
是一个接口,它是Spring中工厂的顶层规范,是SpringIoc容器的核心接口,它定义了getBean()
、containsBean()
等管理Bean的通用方法。Spring的容器都是它的具体实现,它负责管理所有的Bean,包括FactoryBean
。
上面说到FactoryBean
可以让我们自定义Bean的创建过程,那么怎么定义呢,方法很简单,只要实现FactoryBean
的getObject
方法即可。看下ProcessEngineFactoryBean
中getObject
的实现:
这里返回的类型也就是这个ProcessEngineFactoryBean
产生的Bean即为Processengine
。说了这么多,可以简单概括为ProcessEngineFactoryBean
主要是负责产生一个Processengine
,实现引擎Bean的注入。
这个抽象类中还注入了其他常用的Bean,例如RuntimeService
,RepositoryService
,HistoryService
,TaskService
等。
与这个过程类似,在初始化的时候还加载了许多其他类型的Bean。
在ProcessEngineFactoryBean
的getObject
方法是为了创建Processengine
,其中最关键的代码:
this.processEngine = this.processEngineConfiguration.buildProcessEngine();
跟进去看这里的buildProcessEngine()
的具体实现:
其中的this.autoDeployResources(processEngine);
会在项目启动的时候将classpath*:**/processes/
目录下的流程图自动部署。可以通过spring.activiti.deployment-mode
这个属性设置各种不同的部署策略。
这次先讲到这里,下次介绍下activiti7
的命令模式。