Activiti 7 集成Spring (一)

238 阅读2分钟

这是我参与更文挑战的第10天,活动详情查看: 更文挑战

虽然你绝对可以在没有 Spring 的情况下使用 Activiti,但我们已经提供了一些非常好的集成特性,这些特性在本章中进行了解释。

ProcessEngineFactoryBean

该ProcessEngine可配置为一个普通的Spring bean。集成的起点是类org.activiti.spring.ProcessEngineFactoryBean。该 bean 采用流程引擎配置并创建流程引擎。这意味着 Spring 属性的创建和配置与配置部分中记录的相同。对于 Spring 集成,配置和引擎 bean 将如下所示:

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
  <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>

请注意,processEngineConfigurationbean 现在使用org.activiti.spring.SpringProcessEngineConfiguration该类。

交易

我们将SpringTransactionIntegrationTest逐步解释在 Spring 示例中发现的分布。下面是我们在本示例中使用的 Spring 配置文件(您可以在 SpringTransactionIntegrationTest-context.xml 中找到它)。下面显示的部分包含 dataSource、transactionManager、processEngine 和 Activiti Engine 服务。

当将 DataSource 传递给SpringProcessEngineConfiguration(使用属性“dataSource”)时,Activiti 在org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy内部使用 a ,它包装了传递的 DataSource。这样做是为了确保从 DataSource 检索到的 SQL 连接和 Spring 事务可以很好地协同工作。这意味着不再需要在 Spring 配置中自己代理数据源,尽管它仍然允许将 a 传递TransactionAwareDataSourceProxy到SpringProcessEngineConfiguration. 在这种情况下,不会发生额外的包装。

确保TransactionAwareDataSourceProxy自己在 Spring 配置中声明 a 时,不要将它用于已经知道 Spring 事务的资源(例如 DataSourceTransactionManager 和 JPATransactionManager 需要未代理的数据源)。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                           http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

  <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driverClass" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
    <property name="username" value="sa" />
    <property name="password" value="" />
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </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="asyncExecutorActivate" value="false" />
  </bean>

  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
  </bean>

  <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
  <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
  <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />

...

Spring 配置文件的其余部分包含我们将在这个特定示例中使用的 bean 和配置:

<beans>
  ...
  <tx:annotation-driven transaction-manager="transactionManager"/>

  <bean id="userBean" class="org.activiti.spring.test.UserBean">
    <property name="runtimeService" ref="runtimeService" />
  </bean>

  <bean id="printer" class="org.activiti.spring.test.Printer" />

</beans>

首先,使用任何 Spring 方法创建应用程序上下文。在此示例中,您可以使用类路径 XML 资源来配置我们的 Spring 应用程序上下文:

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
	"org/activiti/examples/spring/SpringTransactionIntegrationTest-context.xml");

或者因为它是一个测试:

@ContextConfiguration("classpath:org/activiti/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")

然后我们可以获取服务 bean 并调用它们的方法。ProcessEngineFactoryBean 将向服务添加一个额外的拦截器,在 Activiti 服务方法上应用 Propagation.REQUIRED 事务语义。因此,例如,我们可以使用 repositoryService 来部署这样的流程:

RepositoryService repositoryService =
  (RepositoryService) applicationContext.getBean("repositoryService");
String deploymentId = repositoryService
  .createDeployment()
  .addClasspathResource("org/activiti/spring/test/hello.bpmn20.xml")
  .deploy()
  .getId();

反过来也行。在这种情况下,Spring 事务将围绕 userBean.hello() 方法,Activiti 服务方法调用将加入同一个事务。

UserBean userBean = (UserBean) applicationContext.getBean("userBean");
userBean.hello();

UserBean 看起来像这样。记得上面在 Spring bean 配置中,我们将 repositoryService 注入到 userBean 中。

public class UserBean {

  /** injected by Spring */
  private RuntimeService runtimeService;

  @Transactional
  public void hello() {
    // here you can do transactional stuff in your domain model
    // and it will be combined in the same transaction as
    // the startProcessInstanceByKey to the Activiti RuntimeService
    runtimeService.startProcessInstanceByKey("helloProcess");
  }

  public void setRuntimeService(RuntimeService runtimeService) {
    this.runtimeService = runtimeService;
  }
}