spring事务从底层掌握其实现原理
流程介绍
主流程介绍
众所周知,Spring事务采用AOP的方式实现,我们从TransactionAspectSupport这个类开始分析。
- 获取事务的属性(@Transactional注解中的配置)
- 加载配置中的TransactionManager.
- 获取收集事务信息TransactionInfo
- 执行目标方法
- 出现异常,尝试处理。
- 清理事务相关信息
- 提交事务
//1. 获取@Transactional注解的相关参数 TransactionAttributeSource tas = getTransactionAttributeSource(); // 2. 获取事务管理器 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. // 3. 获取TransactionInfo,包含了tm和TransactionStatus TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. // 4.执行目标方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { //5.回滚 // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 6. 清理当前线程的事务相关信息 cleanupTransactionInfo(txInfo); } // 提交事务 commitTransactionAfterReturning(txInfo); return retVal; }
- 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
doBegin做了什么
在执行createTransactionIfNecessary获取事务状态时,就准备好了开启事务的所有内容,主要是执行了JDBC的con.setAutoCommit(false)方法。同时处理了很多和数据库连接相关的ThreadLocal变量。
关键对象介绍
PlatformTransactionManager
TransactionManager是做什么的?它保存着当前的数据源连接,对外提供对该数据源的事务提交回滚操作接口,同时实现了事务相关操作的方法。一个数据源DataSource需要一个事务管理器。
属性:DataSource
内部核心方法:
public commit 提交事务
public rollback 回滚事务
public getTransaction 获得当前事务状态
protected doSuspend 挂起事务
protected doBegin 开始事务,主要是执行了JDBC的con.setAutoCommit(false)方法。同时处理了很多和数据库连接相关的ThreadLocal变量。
protected doCommit 提交事务
protected doRollback 回滚事务
protected doGetTransaction() 获取事务信息
final getTransaction 获取事务状态
获取对应的TransactionManager
@Nullable protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) { // Do not attempt to lookup tx manager if no tx attributes are set if (txAttr == null || this.beanFactory == null) { return getTransactionManager(); }
String qualifier = txAttr.getQualifier(); //如果指定了Bean则取指定的PlatformTransactionManager类型的Bean if (StringUtils.hasText(qualifier)) { return determineQualifiedTransactionManager(this.beanFactory, qualifier); } //如果指定了Bean的名称,则根据bean名称获取对应的bean else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } else { // 默认取一个PlatformTransactionManager类型的Bean PlatformTransactionManager defaultTransactionManager = getTransactionManager(); if (defaultTransactionManager == null) { defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY); if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } } return defaultTransactionManager; } }
- 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
可以看到,如果没有指定TransactionManager参数的话,会使用默认的一个实现,所以当程序中有多个数据库时,事务执行最好是指定事务管理器。
事务的信息TransactionInfo
TransactionInfo是对当前事务的描述,其中记录了事务的状态等信息。它记录了和一个事务所有的相关信息。它没有什么方法,只是对事务相关对象的一个组合。最关键的对象是TransactionStatus,它代表当前正在运行的是哪个事务。
1.核心属性:事务状态TransactionStatus
2.事务管理器
3.事务属性
4.上一个事务信息oldTransactionInfo,REQUIRE_NEW传播级别时,事务挂起后前一个事务的事务信息
当前事务状态TransactionStatus
通过TransactionManager的getTransaction方法,获取当前事务的状态。
具体是在AbstractPlatformTransactionManager中实现.
TransactionStatus被用来做什么:TransactionManager对事务进行提交或回滚时需要用到该对象
具体方法有:
作用:
-
判断当前事务是否是一个新的事务,否则加入到一个已经存在的事务中。事务传播级别REQUIRED和REQUIRE_NEW有用到。
-
当前事务是否携带保存点,嵌套事务用到。setRollbackOnly,isRollbackOnly,当子事务回滚时,并不真正回滚事务,而是对子事务设置一个标志位。
-
事务是否已经完成,已经提交或者已经回滚。
传播级别
介绍
Spring事务的传播级别描述的是多个使用了@Transactional注解的方法互相调用时,Spring对事务的处理。包涵的传播级别有:
1、REQUIRED, 如果当前线程已经在一个事务中,则加入该事务,否则新建一个事务。
2、SUPPORT, 如果当前线程已经在一个事务中,则加入该事务,否则不使用事务。
3、MANDATORY(强制的),如果当前线程已经在一个事务中,则加入该事务,否则抛出异常。
4、REQUIRES_NEW,无论如何都会创建一个新的事务,如果当前线程已经在一个事务中,则挂起当前事务,创建一个新的事务。
5、NOT_SUPPORTED,如果当前线程在一个事务中,则挂起事务。
6、NEVER,如果当前线程在一个事务中则抛出异常。
7、NESTED, 执行一个嵌套事务,有点像REQUIRED,但是有些区别,在Mysql中是采用SAVEPOINT来实现的。
挂起事务,指的是将当前事务的属性如事务名称,隔离级别等属性保存在一个变量中,同时将当前线程中所有和事务相关的ThreadLocal变量设置为从未开启过线程一样。Spring维护着一个当前线程的事务状态,用来判断当前线程是否在一个事务中以及在一个什么样的事务中,挂起事务后,当前线程的事务状态就好像没有事务。
现象描述
@Service public class MyTsA { @Resource private UserServiceImpl userService; @Resource private MyTsB myTsB;
@Transactional(rollbackFor = Exception.class) public void testNewRollback(){ User user = new User(); user.setId(1); user.setName("张三"); userService.save(user); myTsB.save(); }
}
@Service
public class MyTsB {
@Resource
private UserServiceImpl userService;
@Transactional(rollbackFor = RuntimeException.class, propagation = ???)
public void save(){
User user = new User();
user.setId(2);
user.setName(“李四”)
userService.save(user);
}
- 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
如上面所示有两个事务A和事务B,事务A方法中调用了事务B方法,区分两种回滚情况。
A提交,B回滚。
A回滚,B提交。
对于不同的传播级别:
1.当传播级别为为REQUIRED时,第一种情况A和B都会回滚。
2.。当传播级别为RQUIRED_NEW时,第一种情况A可以成功提交,B回滚,第二种情况A回滚,B可以正确提交,二者互不影响。(在A事务捕获B事务异常的情况下,保证A事务提交)
3.当传播级别为NESTED时,第一种情况A可以正常提交,B回滚,第二种情况二者都会回滚。
原理
我们从两个角度看他们的实现原理,一个是刚进入事务时,针对不同的传播级别,它们的行为有什么区别。另一个角度是当事务提交或者回滚时,传播级别对事务行为的影响。
首先在尝试获取事务信息时,如果当前已经存在一个事务,则会根据传播级别做一些处理:
隔离级别对开始事务的影响(获取TransactionStatus)
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
// 从当前的transactionManager获取DataSource对象
// 然后以该DataSource对象为Key,
// 去一个ThreadLocal变量中的map中获取该DataSource的连接
// 然后设置到DataSourceTransactionObject中返回。
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();
}
// 如果当前线程已经在一个事务中了,则需要根据事务的传播级别
//来决定如何处理并获取事务状态对象
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
//如果当前不在一个事务中,则执行事务的准备操作
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 构造事务状态对象,注意这里第三个参数为true,代表是一个新事务
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//执行begin操作,核心操作是设置隔离级别,执行 conn.setAutoCommit(false); 同时将数据连接绑定到当前线程
doBegin(transaction, definition);
// 针对事务相关属性如隔离级别,是否在事务中,设置绑定到当前线程
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
- 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
可以看到,如果当前不存在事务时,创建一个新的TransactionStatus对象,否则进入到handleExistingTransaction。下面来看这个方法
1.如果是NEVER传播级别则抛出异常
2. 如果是不支持,则挂起事务,将当前事务对象设置为null,newTransaction设置为false,把线程的相关Threadlocal变量改的就像当前不存在事务一样
3. 如果是required_NEW的话,则挂起当前事务,同时创建一个新的事务,执行doBegin操作,设置newTransaction为true
4.如果是嵌入事务,则创建一个SAVEPOINT
5.对于REQUIRED传播级别会把newTransaction标志位设置为false
/** * Create a TransactionStatus for an existing transaction. */ private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { //如果是NEVER传播级别则抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } // 如果是不支持,则挂起事务 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); //挂起事务同时将当前事务设置为null,newTransaction设置为false,把线程的相关Threadlocal变量改的就像当前不存在事务一样 return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } //如果是required_NEW的话,则挂起当前事务,同时创建一个新的事务,执行doBegin操作 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } SuspendedResourcesHolder suspendedResources = suspend(transaction); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } } // 如果是嵌入事务,则创建一个SAVEPOINT if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } }
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { logger.debug("Participating in existing transaction"); }
//这里判断是否需要对已经存在的事务进行校验,这个可以通过AbstractPlatformTransactionManager.setValidateExistingTransaction(boolean)来设置,设置为true后需要校验当前事务的隔离级别和已经存在的事务的隔离级别是否一致
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException(“Participating transaction with definition [” +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
“(unknown)”));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException(“Participating transaction with definition [” +
definition + “] is not marked as read-only but existing transaction is”);
}
}
}
// 如果不设置是否校验已经存在的事务,则对于REQUIRED传播级别会走到这里来,这里把newTransaction标志位设置为false,
// 这里用的definition是当前事务的相关属性,所以隔离级别等依然是当前事务的(子事务),而不是已经存在的事务的隔离级别(父事务)
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
隔离级别对回滚事务的影响
1、如果newTransaction设置为ture,则真正执行回滚。
2、如果有保存点,则回滚到保存点。
3、否则不会真正回滚,而是设置回滚标志位。
private void processRollback(DefaultTransactionStatus status, boolean unexpected) { try { boolean unexpectedRollback = unexpected; try { triggerBeforeCompletion(status); // 如果有保存点 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Rolling back transaction to savepoint"); } status.rollbackToHeldSavepoint(); } // 如果是新的事务,当传播级别为RUQUIRED_NEW时会走到这里来 else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback"); } doRollback(status); } else { // 加入到事务中,设置回滚状态,适用于REQUIRED传播级别 // 并不会真的回滚,而是设置回滚标志位 // Participating in larger transaction if (status.hasTransaction()) { if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug("Participating transaction failed - marking existing transaction as rollback-only"); } doSetRollbackOnly(status); } else { if (status.isDebug()) { logger.debug("Participating transaction failed - letting transaction originator decide on rollback"); } } } else { logger.debug("Should roll back transaction but cannot - no transaction available"); } // Unexpected rollback only matters here if we're asked to fail early if (!isFailEarlyOnGlobalRollbackOnly()) { unexpectedRollback = false; } } } catch (RuntimeException | Error ex) { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw ex; }
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); // Raise UnexpectedRollbackException if we had a global rollback-only marker if (unexpectedRollback) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } } finally { cleanupAfterCompletion(status); } }
- 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
隔离级别对提交事务的影响
1、就算事务方法没有抛出异常,走到了commit方法中,但是依然有可能回滚事务。
2、对于REQUIRED传播级别,即使父事务中没有抛出异常,但是子事务中已经设置了回滚标志,那么父事务依然会回滚
3、只有newTransaction标志位为true的事务才会真正执行commit操作。
@Override 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, false); return; }
// 对于REQUIRED传播级别,即使父事务中没有抛出异常,但是子事务中已经设置了回滚标志,那么父事务依然会回滚
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug(“Global transaction is marked as rollback-only but transactional code requested commit”);
}
processRollback(defStatus, true);
return;
}
processCommit(defStatus);
}
- 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
为什么我的事务不生效
1.如果不是Innodb存储引擎,MyISAM不支持事务。
2.没有指定rollbackFor参数。
3. 没有指定transactionManager参数,默认的transactionManager并不是我期望的,以及一个事务中涉及到了多个数据库。
4. 如果AOP使用了JDK动态代理,对象内部方法互相调用不会被Spring的AOP拦截,@Transactional注解无效。
5. 如果AOP使用了CGLIB代理,事务方法或者类不是public,无法被外部包访问到,或者是final无法继承,@transactional注解无效。
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
获取事务的属…
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f1865d482bfc2a8f9b374e2b9ff223b5.png)
![表情包](https://i-blog.csdnimg.cn/blog_migrate/3df739fbf0a0daf6dcc4d6d06cae3040.png)
![](https://i-blog.csdnimg.cn/blog_migrate/98fb45ff3ee45819903f5955b5ec12f1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bc1b0995e6e4f0d0bc3101c48030f87b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2fa1cadbd6f9667972aa68dac296e32b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/62460b89fb4c26ce71bf3789a389cfce.png)
![](https://i-blog.csdnimg.cn/blog_migrate/951829b0880772706ebde1134f3ec49c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b17ec15f3075b478637ebb713ad52690.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ca9d6829319576e722bf6b0c3d26f56d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/27c20afc0e17c9b94fdf931b1b2a13f0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/aee3957e06083a436fec6f52f02bf929.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9d0266bfaa3e93ba4dd8f71b58fc2d57.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f0cbf30a9cde3bfea150285ba823f241.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9bdbfa5b63e2a41661fa969fd10d77ce.png)
![](https://i-blog.csdnimg.cn/blog_migrate/837414786bd6006c4a63b6ce4e93ca7e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6b4162d001afa75b032b938d66e5b4f5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/191cfce78416d6734c3b34fadbc4f834.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f8f8581a3b9b9390a1fb45879a9c4da.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1bb9b491090e15c3ae2ad1c4dc56a82f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/69323fb546c998bff6aad082dda13ddb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cab96bb8c57e124d6e1d883024e77bc5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/492214adf07e239ddf755f60bcd793f3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a927d443b4275fbb493279cbb7a6b9a1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/395e04f0965050e192d1a6533d02e2ae.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ed76e065f4757bee9744df3e4937e3b7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/787c3814a18b74b33b542afc78b6f1a3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7e1cf50b2c808b5031de6d054dbebfd5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a0eeabdb135fef217c0230029c55683c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/807a9b55b2dd24aa5bfe31d92a8bb7f2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e0c3f123fcf84e37465a0f759e6f5a80.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f341bd3ddfac7d7ed3735b6db259cc0d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/667ded19275da4d9c2c7bd92aaa73956.png)
![](https://i-blog.csdnimg.cn/blog_migrate/03dc527a9b36a5f6330f6417b05f5171.png)
![](https://i-blog.csdnimg.cn/blog_migrate/03ce5692d5f5f91c1e221109827fbb49.png)
![](https://i-blog.csdnimg.cn/blog_migrate/44921c707af3ef9384111b786ac4e543.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ba1ca17339b10b548457d1c5c9b48325.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0f8cc2c64f7876317ce0f21ec0cbbe54.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9f844eb7f7cf69760c54b78b0b9fcdab.png)
![](https://i-blog.csdnimg.cn/blog_migrate/83eed18a779a02c8ab512ed3e55e0e04.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5ab297c793a759c5709d5a2a760d9613.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8f38bd1a5ba1fd60c1ac086902c4ac7e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f9050c3f95e7630966e015f579d3e61b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e32b824a919ddac30b4bb6a56f7641a3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/acaa1c9ae1ba6752619cd5b27f468aaa.png)
![](https://i-blog.csdnimg.cn/blog_migrate/204932a385689f89d8fce1b39d662905.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d78c05f751f66bd249257b450716ceb5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3388ee84b8a8739fbecb00ecdd974727.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cfc2d8c0c6c537993fa46ea6b370ebe7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/263a81eff908bd0082aabf65123e3a49.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5bf1b07c76c4148b0f9804c7213003b4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c2c098a7f1e7d2a672e7773e05dc743f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/70859dcc09460749f196e56ee3459537.png)
![](https://i-blog.csdnimg.cn/blog_migrate/35e6064f79f43916699ed60c0301768a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bbc87b72fefd291a2a37504edb56bdd0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a453d15321953344f237f7f4cf825fd1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a5a663da6816c53a10751c4c132c3918.png)
![](https://i-blog.csdnimg.cn/blog_migrate/30fda9e7e929a0ff564bbc8ede1cc5cc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/10b0a4aad7077098659fa43d875699f1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0672cf608a10a0b6d469a8a0be9561cf.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0abb57ec30c3864a497c5b80883e6bc5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/505f4e17d9b788f5c24e74919c131177.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8e146d100a236d8a8a9855a5df4b2d3d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bf4036ae16bb04ee29c92d8769f1f0b7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0a08bf8d22490890270645b015c65f1e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c83c656b5353c7aa1728456cb8647c06.png)
![](https://i-blog.csdnimg.cn/blog_migrate/979dedf9196d70044a28182460b819cd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c928d384e503dcf98f49060659086e87.png)
![](https://i-blog.csdnimg.cn/blog_migrate/de84146bf805e0d5ad43202af5fe034b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/56db96d99ce089c3a6ba4ac206a10175.png)
![](https://i-blog.csdnimg.cn/blog_migrate/33bdb911ec395abf0ef8c81254cf1107.png)
![](https://i-blog.csdnimg.cn/blog_migrate/efaa72156b4138c36d68d0aa89dd853e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b46f523f29569b55b03cb9c839814c6e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2db0f9ced16b56177e4b301c0352a2de.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d1bca1722ae4a8fce2fad7eb4d8a43da.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
事务,大家所熟悉的事务(Transaction),基本上会就往Spring事务靠。其实Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务。
事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
前面已经有一篇文章讲过了如何在Spring中使用声明式事务,并对一些特性进行了讲解,具体如下:Spring事务管理-使用基础
这一篇文章从SpringBoot启动出发,到Spring实现事务管理,从源码角度,分
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
简单案例,保存订单,修改商品数量
就是这两个方法,第一个方法中引用了第二个方法,都用@Transactional注解。debug调用shopping方法。
spring事务实现的源码
在调用方法时会扫描@Transactional,进入方法前会判断是否有注解(在…
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
原生的事务管理
在没有Spring存在的时候,事务就已经诞生了…
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
事务是区分文件存储系统与Nosql数据库重要特性之一,其存在的意义是为了保证即使在并发情况下也能正确的执行crud操作。怎样才算是正确的呢?这时提出了事务需要保证的四个特性即ACID:
A: 原子性(atomicity)
事务中各…
Spring声明式事务让我们从复杂的事务处理中得到解脱,使我们再也不用去处理这些步骤:获得连接、关闭连接、事务提交和回滚操作。再也不需要在事务相关方法中处理大量的try…catch…finally代码。
Spring中事务的使用虽然已经相对简单的多,但是…
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
先来个简单的介绍吧!
SpringCloud框架
针对这个架构图我分层介绍一下:
1、是web服务器的选型,这个我选择的是nginx+keepalived,haproxy也是一个选择,但是haproxy在反向代理处理跨域访问的时候问题很多…
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
Spring事务处理,是将事务处理的工作统一起来,并为事务处理提供通用的支持。
2、工作原理及实现
a、划分处理单元——IOC
由于spring解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用spring中的IOC划分了事务处理单元。并且将对事务的各种配置放到了ioc容器中(设置事务管理器,设置事务
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c435921c498fd8cf48f9f07527be548a.png)
1.1 Spring Data Jpa底层原理解析
目标:知道它是怎么运行的?底层到底封装的是谁?、
明确一点:我们所使用的所有框架,底层大多数都使用了动态代理技术、反射技术来封装实现。
分析步骤:
我们只写了接口,但是没有写实现类,这个实现类就是Spring在运行的时候,注入的代理对象。
Spring怎么知道生成的那个dao的实现类?因为在配置文件中指定了dao接口所在的…
热门文章
最新评论
- Git 最常用命令速查手册,值得收藏!
扎克风暴: 大牛一出手就知有没有
- Seata事务操作实战,快速搞定分布式事务
元梦人: 优秀 不过为什么要装python?必须的?
- spring中动态数据源切换失效问题剖析
不归徒_bin: 我的问题事物问题解决了, https://blog.csdn.net/D_19901719576/article/details/115556780
- 带有@Transactional和@Async的循环依赖问题
qq_35118395: 注入的属性bean和缓存中得bean不是同一个,有点牛逼啊
- MergedBeanDefinitionPostProcessor和@Autowired,@Value的关系
轻云K: 牛逼
最新文章
举报
![](https://i-blog.csdnimg.cn/blog_migrate/4854f51df06a90d018cde83782c096d9.png)
- 内容涉黄
- 政治相关
- 内容抄袭
- 涉嫌广告
- 内容侵权
- 侮辱谩骂
- 样式问题
- 其他