原创:一叶知秋(549051701)
版权:归作者与公司所有。
Activiti是目前比较流行的工作流引擎,它的前身是jBPM4。自jBPM5以后activiti已经成为一个独立的项目,并从jBPM中分离出来。本方只详解如何实现activiti与业务代码形成共治的事务。更多activiti技术请继续关注。
由于activiti是通过MyBatis做的数据影射。且可以很好的与Spring整合,此处直接使用Spring来管理事务。
1:添加maven依赖
以下是Activiti的核心依赖:
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.19.0.2</version>
</dependency>
以下是Activiti开的spring依赖:(导入以下依赖以后,会同时自动添加spring的所有依赖)
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.19.0.2</version>
</dependency>
以下是spring依赖的weave织入依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
2:相关类介绍
使用spring管理的事务,核心就是如何创建ProcessEngineConfiguration类,此处在activiti-spring的依赖中activiti提供了:org.activiti.spring.SpringProcessEngineConfiguration类。同时activiti还提供了:org.activiti.spring.ProcessEngineFactoryBean类用于创建ProcessEngine核心类。即:
创建ProcessEngineConfiguration:
<!-- 创建ProcessEngineConfiguration使用SpringProcessEngineConfiguration类此类由Activiti提供且放到activiti-spring.jar包中 -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="databaseSchemaUpdate" value="true"></property>
<!-- 必须配置TransactionManager -->
<property name="transactionManager" ref="transactionManager"></property>
</bean>
创建ProcessEngine:
<!-- 创建ProcessEngine -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
3:在配置的同时,同时添加Spring的事务
配置Spring事务是通用做法,相信大家都已经了解:
<!-- 声明DataSource事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置上自己的事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<tx:method name="set*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
<!-- 配置aop切面-->
<aop:config>
<aop:pointcut expression="execution(* cn..service.*Service.*(..))"
id="cut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="cut" />
</aop:config>
4:完整的配置代码
以下是完整的配置代码,可以根据自己数据库及切面的不同进行相应的调整:
<!-- 配置数据库连接 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl">
<value><![CDATA[jdbc:mysql:///activiti?characterEncoding=UTF-8&useSSL=false]]></value>
</property>
<property name="user" value="root" />
<property name="password" value="e234" />
<property name="checkoutTimeout" value="3000"></property>
<property name="maxPoolSize" value="3"></property>
</bean>
<!-- 声明DataSource事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置上自己的事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<tx:method name="set*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* cn..service.*Service.*(..))"
id="cut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="cut" />
</aop:config>
<!-- 创建ProcessEngineConfiguration使用SpringProcessEngineConfiguration类此类由Activiti提供且放到activiti-spring.jar包中 -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="databaseSchemaUpdate" value="true"></property>
<!-- 必须配置TransactionManager -->
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!-- 创建ProcessEngine -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<!-- 获取ProcessEngine的一些服务 -->
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService"></bean>
5:测试代码
在配置完成以后,应该对是否已经进行了事务控制,进行一个完整的测试。
所以,本处提供了以下的程序结构:
配置代码:
<!--============配置程序类================= -->
<bean id="testService" class="cn.transaction.service.TransactionService">
<property name="dao">
<bean class="cn.transaction.dao.TransactionDao">
<property name="dataSource" ref="dataSource"></property>
</bean>
</property>
<property name="repositoryService" ref="repositoryService"></property>
</bean>
核心Service层的代码如下:
package cn.transaction.service;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import cn.transaction.dao.TransactionDao;
public class TransactionService {
private TransactionDao dao;
private RepositoryService repositoryService;
//用于注入activiti的仓库/部署服务
public void setRepositoryService(RepositoryService repositoryService) {
this.repositoryService = repositoryService;
}
//用于注入程序中的Dao
public void setDao(TransactionDao dao) {
this.dao = dao;
}
public void save() {
/**
* 可以先操作activiti的操作,一般都不会出现异常<br>
* 后面如果自己的代码出现异常,则可以回滚activiti,但生成的id不会回滚
*/
Deployment deployment = repositoryService.createDeployment()//
.name("测试事务2")//
.addClasspathResource("cn/usertask/userTask.bpmn")//
.addClasspathResource("cn/usertask/userTask.png")//
.deploy();
System.err.println("ID:"+deployment.getId());
/**
* 然后再做自己的操作--个人建议可以将自己的操作放到activiti之前操作
*/
dao.save();
}
}
经过上面的测试,已经共用同一个事务。测试成功。
6:总结
1:核心点在于activiti提供的SpringProcessEngineConfiguration类,此类要求用户必须要提供TransactionManager事务管理者,否则在启动时会抛出异常。
2:在创建ProcessEngine之后,可以通过工厂方法,获取ProcessEngine的所有核心服务,如:
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService"></bean>
3:使用spring的aop实现共治的事务。
4:依然在Service层控制事务。