Spring的事务架构

Spring的事务架构
事务处理是数据库访问层非常重要的一项操作,那么Spring给我们提供的事务是一个什么样的事务呢?

Spring 声明式事务处理

概念

程序员不再负责处理事务,事务处理交给Spring容器来做。程序员做的是声明。那么声明什么呢?
具体声明:
程序员负责的两个内容:

  • 对表的CRUD操作:目标类的目标方法
  • 告诉Spring容器什么样的目标方法采用什么样的事务策略来处理。

Spring 容器负责(切面):事务的处理

Spring采用的实现原理:采用AOP技术来实现的。

Spring 事务的架构

分析Spring的事务的架构我们从他的几个事务的管理的几个类源码中看吧:
下面直接放代码了!

PlatformTransactionManager类部分源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public interface PlatformTransactionManager {
/**
* Return a currently active transaction or create a new one, according to
* the specified propagation behavior.
* <p>Note that parameters like isolation level or timeout will only be applied
* to new transactions, and thus be ignored when participating in active ones.
* <p>Furthermore, not all transaction definition settings will be supported
* by every transaction manager: A proper transaction manager implementation
* should throw an exception when unsupported settings are encountered.
*/
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
/**
* Commit the given transaction, with regard to its status. If the transaction
* has been marked rollback-only programmatically, perform a rollback.
* <p>If the transaction wasn't a new one, omit the commit for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after committing the new one.*/
void commit(TransactionStatus status) throws TransactionException;
/**
* Perform a rollback of the given transaction.
* <p>If the transaction wasn't a new one, just set it rollback-only for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after rolling back the new one.
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
* The transaction will already have been completed and cleaned up when commit
* returns, even in case of a commit exception. Consequently, a rollback call
* after commit failure will lead to an IllegalTransactionStateException
*/
void rollback(TransactionStatus status) throws TransactionException;
//.....
}

AbstractPlatformTransactionManager类部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@SuppressWarnings("serial")
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
//---------------------------------------------------------------------
// Implementation of PlatformTransactionManager
//---------------------------------------------------------------------
/**
* This implementation handles propagation behavior. Delegates to
* {@code doGetTransaction}, {@code isExistingTransaction}
* and {@code doBegin}.
* @see #doGetTransaction
* @see #isExistingTransaction
* @see #doBegin
*/
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
//......
}
// rollback已经实现
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus);
}
//已经实现
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus);
// Throw UnexpectedRollbackException only at outermost transaction boundary
// or if explicitly asked to.
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
return;
}
processCommit(defStatus);
}
//.....
}

DataSourceTransactionManager类源码 不在tx事务包中,而是在JDBC的包中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SuppressWarnings("serial")
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
private DataSource dataSource;
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
//......
}

HibernateTransactionManager类源码,在orm包下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@SuppressWarnings("serial")
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
private SessionFactory sessionFactory;
private DataSource dataSource;
private boolean autodetectDataSource = true;
private boolean prepareConnection = true;
private boolean hibernateManagedSession = false;
private boolean earlyFlushBeforeCommit = false;
// ......
@Override
protected Object doGetTransaction() {
HibernateTransactionObject txObject = new HibernateTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if (sessionHolder != null) {
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound Session [" +
SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
}
txObject.setSessionHolder(sessionHolder);
}
// ...
}

通过观察源代码的分析,Spring的事务的整体架构 如下图:
Spring的事务架构

从图中可以知道,HibernateTransactionManager和DataSourceTransactionManager都是继承于AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager实现了PlatformTransactionManager接口,其中AbstractPlatformTransactionManager是一个抽象类, 实现了一部分的方法,还有一些方法是抽象的,那么这样的目的是在于干什么呢?

目的是在于: 面向接口编程,

那么Spring他就怎么面向接口编程的了?
所以根据上面的分析的Spring的事务架构,可以知道,只要我们遵循Spring中的那套事务规范,并且实现了,那么Spring内部就可以按照我们的要求处理数据库,而不管是处理什么数据,不管不同数据库操作方式的不同,只要准许这个架构,那么就可以集成到Spring中去,Spring内部准备可一个壳子,只要你往里面填东西,人家Spring就可以帮你干活了。

再来看AbstractPlatformTransactionManager抽象类不管是它的作用还是一任何一个Java的抽象,抽象类的作用是: 将公共的方法实现了,然后不同的方法就声明为抽象,那么谁继承,那谁就实现。

所以,AbstractPlatfromTransactionManager, 为什么获取事务被整成抽象的方法? 因为不同的数据库技术,获取数据库事务是不同的, 比如说JDBC是通过一个方法connection.setAutoCommit(flase),获取事务,为隐式操作,事务和数据库链接是非常紧密的。

事务的定义

在顶层的PlatformTransactionManager类中我们发现有一个TransactionDefinition类,那么这个类是什么呢?里面有什么呢?先来看下面的源码吧!

TransactionDefinition 类部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface TransactionDefinition {
//事务的传播机制
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
// 隔离机制
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
int TIMEOUT_DEFAULT = -1;
//.....
}

从类名可以知道,这个类是Spring用来描述事务的。其中这个类主要的有两个功能是:

  1. 描述事务的传播机制
  2. 描述事务的隔离机制

那么什么叫传播机制? 主要用于解决什么问题的呢?我们先来看下面的一种情况:

假设有一个Service层中有一个AService类,里面有一个aService方法,它调用了Dao层BDao和CDao类中的bDao和cDao方法,那么如果bDao和cDao在处理的时候分别存在事务,我们在aService方法中,本身也是存在一个事务的,那么加入该方法里面的bDao和cDao中的事务怎么处理呢?

1
2
3
4
5
6
7
8
9
10
11
12
AService{
aService(){//txa
bDao();
cDao();
}
}
BDao:
bDao(){//txb
}
CDao:
cDao(){//txc
}

那么在aService中共有多少个事务?很显然,有三个事务,这个是不允许的呀,一个方法中有三个事务。那么怎么解决呢?这个问题是属于事务嵌套的问题,那么Spring中的事务传播机是用来解决事务的嵌套问题。Spring中有如下几种传播机制:
Spring中的事务传播机制
一般情况下我们选择的是第一个。

那么是隔离机制是为了数据的规范性的约束机制了,它和数据的隔离机制很相似,那么我们来看一下几种事务的隔离级别:

下面是Spring的隔离机制:
Spring中的隔离机制

隔离机制越高,效率越低,数据规范性越强,隔离机制越低,效率越高,数据就越烂(可能读取脏数据等)。

说明:通过Spring的事务处理架构,再通过配置文件,配置具体的实现事务的类,就可以让Spring容器知道是什么样的技术来操作数据库,通过对事务状态的判断,通过事务的定义,就让Spring可以知道具体的目标方法采用什么样的事务策略来处理了。

坚持原创技术分享,您的支持将鼓励我继续创作!