• 1、模型
  • 2、解耦
  • 3、实现
    • 3.1 核心接口
    • 3.2 代码分析
      • 3.2.1 事务管理
      • 3.2.2 数据访问
  • 4、使用
    • 4.1 编程模式
    • 4.2 配置模式
      • 4.2.1 声明式配置方式
      • 4.2.2 注解式配置方式
  • 5、总结

在一般的编程习惯中,Spring的数据访问和事务处理的层次结构归纳如下图所示:

Spring数据访问和事务

                                                          图. 1

2、解耦

Spring事务作为一个独立的组件,其目的就是为了与数据访问组件进行分离,这也是Spring事务框架设计的原则。根据这一职责清晰的原则,Spring在设计时就对事务和数据访问进行了很好的职责划分,这个可以从spring-tx和spring-jdbc这两个包就可以看出来。

但是在实际的代码中,会遇到一个棘手的问题:事务和数据访问操作都需要同一个数据库连接资源,那么它们之间怎么传递呢?

这里涉及三个方面:一是线程安全,二是资源的唯一性,三是事务和数据访问的解耦。

Spring数据访问和事务

                                                                                     图. 2

在图2中的1、2和3这三个地方都需要使用数据库连接,并且是同一个连接。Spring的做法是将该连接放在一个统一的地方,要使用该资源,都从这个地方获取,这样就解决了事务模块和数据访问模块之间的紧耦合。

解除耦合之后,对于不同的ORM技术,则需要提供不同的事务管理实现,如下图所示:

Spring数据访问和事务

                                                                              图. 3

3、实现

3.1 核心接口

Spring事务框架的核心接口是:TransactionDefinition,TransactionStatus和PlatformTransactionManager。

TransactionDefinition用于定义事务属性,包括事务的隔离级别,事务的传播行为,事务的超时时间和是否为只读事务。对于隔离级别和传播行为这里就不深入了,可以网上找到很多资料。事务的超时时间就是一个事务需要在规定的时间里完成。只读事务表示在一个事务里不允许进行写操作。

TransactionStatus表示整个事务处理过程中的事务状态,通过事务状态可以进行事务的相应操作。

PlatformTransactionManager是对整个事务行为的抽象,定义了一个完整事务过程中的相关操作。对于不同的ORM技术,需要有不同的实现。

3.2 代码分析

下面简单分析一下事务和数据访问之间数据库连接资源是如何传递的,以JdbcTemplate为例,代码如下:

3.2.1 事务管理

Spring数据访问和事务

                                                             图. 4

代码1:事务管理器首先获取事务对象(具体步骤请看代码2),然后根据事务对象判断是否已经存在事务,如果已经存在事务,则根据传播特性做进一步处理,这里就不介绍了;如果不存在事务,则开启一个新事务,开启新事务的具体内容见代码3。

 1 //************************************** 代码1: AbstractPlatformTransactionManager.java ****************************
 2 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
 3    Object transaction = doGetTransaction();                                                   //获取事务
 4    ......
 5    if (isExistingTransaction(transaction)) {                                                  //如果已经存在事务,则根据传播特性再进一步处理
 6       // Existing transaction found -> check propagation behavior to find out how to behave.
 7       return handleExistingTransaction(definition, transaction, debugEnabled);
 8    }
 9  
10    // No existing transaction found -> check propagation behavior to find out how to proceed.
11    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
12       throw new IllegalTransactionStateException(
13             "No existing transaction found for transaction marked with propagation 'mandatory'");
14    }
15    else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||  //如果不存在事务,则开启一个新事务
16          definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
17       definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
18       SuspendedResourcesHolder suspendedResources = suspend(null);
19        
20       try {
21          boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
22          DefaultTransactionStatus status = newTransactionStatus(
23                definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
24          doBegin(transaction, definition);                                                      //开启事务
25          prepareSynchronization(status, definition);
26          return status;
27       }
28       ......
29    }
30    ......
31 }
View Code

相关文章: