• 【源码阅读】事务源码


    拜神

    看源码先拜神,事务管理的顶级接口 PlatformTransactionManager 是 Rod Johnson 和 Juergen Hoeller 两位大神写的。嗯,我看的大多源码都是拜 Juergen Hoeller 这位大神
    在这里插入图片描述
    在这里插入图片描述

    编程式事务

    接口介绍

    1. Spring 事务的三大接口:PlatformTransactionManager、TransactionDefinition、TransactionStatus
    2. TransactionTemplate 是对上述三个接口的封装,采用了模板设计模式

    PlatformTransactionManager

    事务管理的顶级接口。该接口其实极其简单,只有三个方法,(1)获取或创建事务;(2)提交事务;(3)回滚事务

    同时为了简化事务管理器的实现,该接口提供了一个抽象类 AbstractPlatformTransactionManager,规定了事务管理器的基本框架,仅将依赖于具体平台的特性作为抽象方法留给子类实现,默认实现有 JtaTransactionManager 和 DataSourceTransactionManager。例如使用 JPA,AbstractPlatformTransactionManager 就有多一个 JpaTransactionManager 的实现

    该接口也在最上边的注释上说明了,该接口是供应用直接使用的,不建议作为 API 的首选,建议使用 TransactionTemplate 或者 基于 AOP 的切面

    /**
     * This is the central interface in Spring's transaction infrastructure.
     * Applications can use this directly, but it is not primarily meant as API:
     * Typically, applications will work with either TransactionTemplate or
     * declarative transaction demarcation through AOP.
     *
     * <p>For implementors, it is recommended to derive from the provided
     * {@link org.springframework.transaction.support.AbstractPlatformTransactionManager}
     * class, which pre-implements the defined propagation behavior and takes care
     * of transaction synchronization handling. Subclasses have to implement
     * template methods for specific states of the underlying transaction,
     * for example: begin, suspend, resume, commit.
     *
     * <p>The default implementations of this strategy interface are
     * {@link org.springframework.transaction.jta.JtaTransactionManager} and
     * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},
     * which can serve as an implementation guide for other transaction strategies.
     *
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @since 16.05.2003
     * @see org.springframework.transaction.support.TransactionTemplate
     * @see org.springframework.transaction.interceptor.TransactionInterceptor
     */
    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.
    	 * <p>An exception to the above rule is the read-only flag, which should be
    	 * ignored if no explicit read-only mode is supported. Essentially, the
    	 * read-only flag is just a hint for potential optimization.
    	 * @param definition the TransactionDefinition instance (can be {@code null} for defaults),
    	 * describing propagation behavior, isolation level, timeout etc.
    	 * @return transaction status object representing the new or current transaction
    	 * @throws TransactionException in case of lookup, creation, or system errors
    	 * @throws IllegalTransactionStateException if the given transaction definition
    	 * cannot be executed (for example, if a currently active transaction is in
    	 * conflict with the specified propagation behavior)
    	 * @see TransactionDefinition#getPropagationBehavior
    	 * @see TransactionDefinition#getIsolationLevel
    	 * @see TransactionDefinition#getTimeout
    	 * @see TransactionDefinition#isReadOnly
    	 */
    	TransactionStatus getTransaction(@Nullable 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.
    	 * <p>Note that when the commit call completes, no matter if normally or
    	 * throwing an exception, the transaction must be fully completed and
    	 * cleaned up. No rollback call should be expected in such a case.
    	 * <p>If this method throws an exception other than a TransactionException,
    	 * then some before-commit error caused the commit attempt to fail. For
    	 * example, an O/R Mapping tool might have tried to flush changes to the
    	 * database right before commit, with the resulting DataAccessException
    	 * causing the transaction to fail. The original exception will be
    	 * propagated to the caller of this commit method in such a case.
    	 * @param status object returned by the {@code getTransaction} method
    	 * @throws UnexpectedRollbackException in case of an unexpected rollback
    	 * that the transaction coordinator initiated
    	 * @throws HeuristicCompletionException in case of a transaction failure
    	 * caused by a heuristic decision on the side of the transaction coordinator
    	 * @throws TransactionSystemException in case of commit or system errors
    	 * (typically caused by fundamental resource failures)
    	 * @throws IllegalTransactionStateException if the given transaction
    	 * is already completed (that is, committed or rolled back)
    	 * @see TransactionStatus#setRollbackOnly
    	 */
    	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.
    	 * @param status object returned by the {@code getTransaction} method
    	 * @throws TransactionSystemException in case of rollback or system errors
    	 * (typically caused by fundamental resource failures)
    	 * @throws IllegalTransactionStateException if the given transaction
    	 * is already completed (that is, committed or rolled back)
    	 */
    	void rollback(TransactionStatus status) throws TransactionException;
    
    }
    
    
    • 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

    TransactionDefinition

    接口注释解释该接口定义 Spring 的事务属性的接口,也就是说一个事务的配置都在这里做,这个接口包含了事务的传播等级、隔离级别、事务是否只读、事务超时时间

    /**
     * Interface that defines Spring-compliant transaction properties.
     * Based on the propagation behavior definitions analogous to EJB CMT attributes.
     *
     * <p>Note that isolation level and timeout settings will not get applied unless
     * an actual new transaction gets started. As only {@link #PROPAGATION_REQUIRED},
     * {@link #PROPAGATION_REQUIRES_NEW} and {@link #PROPAGATION_NESTED} can cause
     * that, it usually doesn't make sense to specify those settings in other cases.
     * Furthermore, be aware that not all transaction managers will support those
     * advanced features and thus might throw corresponding exceptions when given
     * non-default values.
     *
     * <p>The {@link #isReadOnly() read-only flag} applies to any transaction context,
     * whether backed by an actual resource transaction or operating non-transactionally
     * at the resource level. In the latter case, the flag will only apply to managed
     * resources within the application, such as a Hibernate {@code Session}.
     *
     * @author Juergen Hoeller
     * @since 08.05.2003
     * @see PlatformTransactionManager#getTransaction(TransactionDefinition)
     * @see org.springframework.transaction.support.DefaultTransactionDefinition
     * @see org.springframework.transaction.interceptor.TransactionAttribute
     */
    public interface TransactionDefinition {
    
    	/**
    	 * Support a current transaction; create a new one if none exists.
    	 * Analogous to the EJB transaction attribute of the same name.
    	 * <p>This is typically the default setting of a transaction definition,
    	 * and typically defines a transaction synchronization scope.
    	 */
    	int PROPAGATION_REQUIRED = 0;
    
    	/**
    	 * Support a current transaction; execute non-transactionally if none exists.
    	 * Analogous to the EJB transaction attribute of the same name.
    	 * <p><b>NOTE:</b> For transaction managers with transaction synchronization,
    	 * {@code PROPAGATION_SUPPORTS} is slightly different from no transaction
    	 * at all, as it defines a transaction scope that synchronization might apply to.
    	 * As a consequence, the same resources (a JDBC {@code Connection}, a
    	 * Hibernate {@code Session}, etc) will be shared for the entire specified
    	 * scope. Note that the exact behavior depends on the actual synchronization
    	 * configuration of the transaction manager!
    	 * <p>In general, use {@code PROPAGATION_SUPPORTS} with care! In particular, do
    	 * not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
    	 * <i>within</i> a {@code PROPAGATION_SUPPORTS} scope (which may lead to
    	 * synchronization conflicts at runtime). If such nesting is unavoidable, make sure
    	 * to configure your transaction manager appropriately (typically switching to
    	 * "synchronization on actual transaction").
    	 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
    	 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
    	 */
    	int PROPAGATION_SUPPORTS = 1;
    
    	/**
    	 * Support a current transaction; throw an exception if no current transaction
    	 * exists. Analogous to the EJB transaction attribute of the same name.
    	 * <p>Note that transaction synchronization within a {@code PROPAGATION_MANDATORY}
    	 * scope will always be driven by the surrounding transaction.
    	 */
    	int PROPAGATION_MANDATORY = 2;
    
    	/**
    	 * Create a new transaction, suspending the current transaction if one exists.
    	 * Analogous to the EJB transaction attribute of the same name.
    	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
    	 * on all transaction managers. This in particular applies to
    	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
    	 * which requires the {@code javax.transaction.TransactionManager} to be
    	 * made available it to it (which is server-specific in standard Java EE).
    	 * <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
    	 * transaction synchronizations. Existing synchronizations will be suspended
    	 * and resumed appropriately.
    	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
    	 */
    	int PROPAGATION_REQUIRES_NEW = 3;
    
    	/**
    	 * Do not support a current transaction; rather always execute non-transactionally.
    	 * Analogous to the EJB transaction attribute of the same name.
    	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
    	 * on all transaction managers. This in particular applies to
    	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
    	 * which requires the {@code javax.transaction.TransactionManager} to be
    	 * made available it to it (which is server-specific in standard Java EE).
    	 * <p>Note that transaction synchronization is <i>not</i> available within a
    	 * {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
    	 * will be suspended and resumed appropriately.
    	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
    	 */
    	int PROPAGATION_NOT_SUPPORTED = 4;
    
    	/**
    	 * Do not support a current transaction; throw an exception if a current transaction
    	 * exists. Analogous to the EJB transaction attribute of the same name.
    	 * <p>Note that transaction synchronization is <i>not</i> available within a
    	 * {@code PROPAGATION_NEVER} scope.
    	 */
    	int PROPAGATION_NEVER = 5;
    
    	/**
    	 * Execute within a nested transaction if a current transaction exists,
    	 * behave like {@link #PROPAGATION_REQUIRED} otherwise. There is no
    	 * analogous feature in EJB.
    	 * <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
    	 * specific transaction managers. Out of the box, this only applies to the JDBC
    	 * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
    	 * when working on a JDBC 3.0 driver. Some JTA providers might support
    	 * nested transactions as well.
    	 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
    	 */
    	int PROPAGATION_NESTED = 6;
    
    
    	/**
    	 * Use the default isolation level of the underlying datastore.
    	 * All other levels correspond to the JDBC isolation levels.
    	 * @see java.sql.Connection
    	 */
    	int ISOLATION_DEFAULT = -1;
    
    	/**
    	 * Indicates that dirty reads, non-repeatable reads and phantom reads
    	 * can occur.
    	 * <p>This level allows a row changed by one transaction to be read by another
    	 * transaction before any changes in that row have been committed (a "dirty read").
    	 * If any of the changes are rolled back, the second transaction will have
    	 * retrieved an invalid row.
    	 * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
    	 */
    	int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
    
    	/**
    	 * Indicates that dirty reads are prevented; non-repeatable reads and
    	 * phantom reads can occur.
    	 * <p>This level only prohibits a transaction from reading a row
    	 * with uncommitted changes in it.
    	 * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
    	 */
    	int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
    
    	/**
    	 * Indicates that dirty reads and non-repeatable reads are prevented;
    	 * phantom reads can occur.
    	 * <p>This level prohibits a transaction from reading a row with uncommitted changes
    	 * in it, and it also prohibits the situation where one transaction reads a row,
    	 * a second transaction alters the row, and the first transaction re-reads the row,
    	 * getting different values the second time (a "non-repeatable read").
    	 * @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
    	 */
    	int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
    
    	/**
    	 * Indicates that dirty reads, non-repeatable reads and phantom reads
    	 * are prevented.
    	 * <p>This level includes the prohibitions in {@link #ISOLATION_REPEATABLE_READ}
    	 * and further prohibits the situation where one transaction reads all rows that
    	 * satisfy a {@code WHERE} condition, a second transaction inserts a row
    	 * that satisfies that {@code WHERE} condition, and the first transaction
    	 * re-reads for the same condition, retrieving the additional "phantom" row
    	 * in the second read.
    	 * @see java.sql.Connection#TRANSACTION_SERIALIZABLE
    	 */
    	int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
    
    
    	/**
    	 * Use the default timeout of the underlying transaction system,
    	 * or none if timeouts are not supported.
    	 */
    	int TIMEOUT_DEFAULT = -1;
    
    
    	/**
    	 * Return the propagation behavior.
    	 * <p>Must return one of the {@code PROPAGATION_XXX} constants
    	 * defined on {@link TransactionDefinition this interface}.
    	 * @return the propagation behavior
    	 * @see #PROPAGATION_REQUIRED
    	 * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
    	 */
    	int getPropagationBehavior();
    
    	/**
    	 * Return the isolation level.
    	 * <p>Must return one of the {@code ISOLATION_XXX} constants defined on
    	 * {@link TransactionDefinition this interface}. Those constants are designed
    	 * to match the values of the same constants on {@link java.sql.Connection}.
    	 * <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
    	 * {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
    	 * transactions. Consider switching the "validateExistingTransactions" flag to
    	 * "true" on your transaction manager if you'd like isolation level declarations
    	 * to get rejected when participating in an existing transaction with a different
    	 * isolation level.
    	 * <p>Note that a transaction manager that does not support custom isolation levels
    	 * will throw an exception when given any other level than {@link #ISOLATION_DEFAULT}.
    	 * @return the isolation level
    	 * @see #ISOLATION_DEFAULT
    	 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
    	 */
    	int getIsolationLevel();
    
    	/**
    	 * Return the transaction timeout.
    	 * <p>Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
    	 * <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
    	 * {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
    	 * transactions.
    	 * <p>Note that a transaction manager that does not support timeouts will throw
    	 * an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
    	 * @return the transaction timeout
    	 */
    	int getTimeout();
    
    	/**
    	 * Return whether to optimize as a read-only transaction.
    	 * <p>The read-only flag applies to any transaction context, whether backed
    	 * by an actual resource transaction ({@link #PROPAGATION_REQUIRED}/
    	 * {@link #PROPAGATION_REQUIRES_NEW}) or operating non-transactionally at
    	 * the resource level ({@link #PROPAGATION_SUPPORTS}). In the latter case,
    	 * the flag will only apply to managed resources within the application,
    	 * such as a Hibernate {@code Session}.
    	 * <p>This just serves as a hint for the actual transaction subsystem;
    	 * it will <i>not necessarily</i> cause failure of write access attempts.
    	 * A transaction manager which cannot interpret the read-only hint will
    	 * <i>not</i> throw an exception when asked for a read-only transaction.
    	 * @return {@code true} if the transaction is to be optimized as read-only
    	 * @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit(boolean)
    	 * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
    	 */
    	boolean isReadOnly();
    
    	/**
    	 * Return the name of this transaction. Can be {@code null}.
    	 * <p>This will be used as the transaction name to be shown in a
    	 * transaction monitor, if applicable (for example, WebLogic's).
    	 * <p>In case of Spring's declarative transactions, the exposed name will be
    	 * the {@code fully-qualified class name + "." + method name} (by default).
    	 * @return the name of this transaction
    	 * @see org.springframework.transaction.interceptor.TransactionAspectSupport
    	 * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
    	 */
    	@Nullable
    	String getName();
    
    }
    
    
    • 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
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247

    这玩意怎么用的呢。我们回头看看 @Transactional 注解

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Transactional {
    
        //...
    	Propagation propagation() default Propagation.REQUIRED;
    
    	Isolation isolation() default Isolation.DEFAULT;
    
        int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
        //...
    }
    
    
    public enum Propagation {
    
    	REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
    
    	SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
    
    	MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
    
    	REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
    
    	NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
    
    	NEVER(TransactionDefinition.PROPAGATION_NEVER),
    
    	NESTED(TransactionDefinition.PROPAGATION_NESTED);
    
    
    	private final int value;
    
    
    	Propagation(int value) {
    		this.value = value;
    	}
    
    	public int value() {
    		return this.value;
    	}
    
    }
    
    public enum Isolation {
    
    	DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
    
    	READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
    
    	READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
    
    	REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
    
    	SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
    
    	private final int value;
    
    	Isolation(int value) {
    		this.value = value;
    	}
    
    	public int value() {
    		return this.value;
    	}
    
    }
    
    
    • 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

    所以就是注解引用了枚举对象,然后枚举对象里边的值其实取自 TransactionDefinition

    TransactionStatus

    记录事务的执行状态,用于flush 或者 回滚

    /**
     * Representation of the status of a transaction.
     *
     * <p>Transactional code can use this to retrieve status information,
     * and to programmatically request a rollback (instead of throwing
     * an exception that causes an implicit rollback).
     *
     * <p>Includes the {@link SavepointManager} interface to provide access
     * to savepoint management facilities. Note that savepoint management
     * is only available if supported by the underlying transaction manager.
     *
     * @author Juergen Hoeller
     * @since 27.03.2003
     * @see #setRollbackOnly()
     * @see PlatformTransactionManager#getTransaction
     * @see org.springframework.transaction.support.TransactionCallback#doInTransaction
     * @see org.springframework.transaction.interceptor.TransactionInterceptor#currentTransactionStatus()
     */
    public interface TransactionStatus extends SavepointManager, Flushable {
    
    	/**
    	 * Return whether the present transaction is new; otherwise participating
    	 * in an existing transaction, or potentially not running in an actual
    	 * transaction in the first place.
    	 */
    	boolean isNewTransaction();
    
    	/**
    	 * Return whether this transaction internally carries a savepoint,
    	 * that is, has been created as nested transaction based on a savepoint.
    	 * <p>This method is mainly here for diagnostic purposes, alongside
    	 * {@link #isNewTransaction()}. For programmatic handling of custom
    	 * savepoints, use the operations provided by {@link SavepointManager}.
    	 * @see #isNewTransaction()
    	 * @see #createSavepoint()
    	 * @see #rollbackToSavepoint(Object)
    	 * @see #releaseSavepoint(Object)
    	 */
    	boolean hasSavepoint();
    
    	/**
    	 * Set the transaction rollback-only. This instructs the transaction manager
    	 * that the only possible outcome of the transaction may be a rollback, as
    	 * alternative to throwing an exception which would in turn trigger a rollback.
    	 * <p>This is mainly intended for transactions managed by
    	 * {@link org.springframework.transaction.support.TransactionTemplate} or
    	 * {@link org.springframework.transaction.interceptor.TransactionInterceptor},
    	 * where the actual commit/rollback decision is made by the container.
    	 * @see org.springframework.transaction.support.TransactionCallback#doInTransaction
    	 * @see org.springframework.transaction.interceptor.TransactionAttribute#rollbackOn
    	 */
    	void setRollbackOnly();
    
    	/**
    	 * Return whether the transaction has been marked as rollback-only
    	 * (either by the application or by the transaction infrastructure).
    	 */
    	boolean isRollbackOnly();
    
    	/**
    	 * Flush the underlying session to the datastore, if applicable:
    	 * for example, all affected Hibernate/JPA sessions.
    	 * <p>This is effectively just a hint and may be a no-op if the underlying
    	 * transaction manager does not have a flush concept. A flush signal may
    	 * get applied to the primary resource or to transaction synchronizations,
    	 * depending on the underlying resource.
    	 */
    	@Override
    	void flush();
    
    	/**
    	 * Return whether this transaction is completed, that is,
    	 * whether it has already been committed or rolled back.
    	 * @see PlatformTransactionManager#commit
    	 * @see PlatformTransactionManager#rollback
    	 */
    	boolean isCompleted();
    
    }
    
    • 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

    TransactionTemplate

    TransactionTemplate 注释的接是就是简化程序化事务划分和事务异常处理的模板类
    比如它继承了 DefaultTransactionDefinition, DefaultTransactionDefinition 定义了事务默认的 TransactionDefinition
    它里边核心的方法是:execute(TransactionCallback action)

    /**
     * Template class that simplifies programmatic transaction demarcation and
     * transaction exception handling.
     *
     * <p>The central method is {@link #execute}, supporting transactional code that
     * implements the {@link TransactionCallback} interface. This template handles
     * the transaction lifecycle and possible exceptions such that neither the
     * TransactionCallback implementation nor the calling code needs to explicitly
     * handle transactions.
     *
     * <p>Typical usage: Allows for writing low-level data access objects that use
     * resources such as JDBC DataSources but are not transaction-aware themselves.
     * Instead, they can implicitly participate in transactions handled by higher-level
     * application services utilizing this class, making calls to the low-level
     * services via an inner-class callback object.
     *
     * <p>Can be used within a service implementation via direct instantiation with
     * a transaction manager reference, or get prepared in an application context
     * and passed to services as bean reference. Note: The transaction manager should
     * always be configured as bean in the application context: in the first case given
     * to the service directly, in the second case given to the prepared template.
     *
     * <p>Supports setting the propagation behavior and the isolation level by name,
     * for convenient configuration in context definitions.
     *
     * @author Juergen Hoeller
     * @since 17.03.2003
     * @see #execute
     * @see #setTransactionManager
     * @see org.springframework.transaction.PlatformTransactionManager
     */
    @SuppressWarnings("serial")
    public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
    
    	/** Logger available to subclasses. */
    	protected final Log logger = LogFactory.getLog(getClass());
    
    	@Nullable
    	private PlatformTransactionManager transactionManager;
    
    
    	/**
    	 * Construct a new TransactionTemplate for bean usage.
    	 * <p>Note: The PlatformTransactionManager needs to be set before
    	 * any {@code execute} calls.
    	 * @see #setTransactionManager
    	 */
    	public TransactionTemplate() {
    	}
    
    	/**
    	 * Construct a new TransactionTemplate using the given transaction manager.
    	 * @param transactionManager the transaction management strategy to be used
    	 */
    	public TransactionTemplate(PlatformTransactionManager transactionManager) {
    		this.transactionManager = transactionManager;
    	}
    
    	/**
    	 * Construct a new TransactionTemplate using the given transaction manager,
    	 * taking its default settings from the given transaction definition.
    	 * @param transactionManager the transaction management strategy to be used
    	 * @param transactionDefinition the transaction definition to copy the
    	 * default settings from. Local properties can still be set to change values.
    	 */
    	public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
    		super(transactionDefinition);
    		this.transactionManager = transactionManager;
    	}
    
    
    	/**
    	 * Set the transaction management strategy to be used.
    	 */
    	public void setTransactionManager(@Nullable PlatformTransactionManager transactionManager) {
    		this.transactionManager = transactionManager;
    	}
    
    	/**
    	 * Return the transaction management strategy to be used.
    	 */
    	@Nullable
    	public PlatformTransactionManager getTransactionManager() {
    		return this.transactionManager;
    	}
    
    	@Override
    	public void afterPropertiesSet() {
    		if (this.transactionManager == null) {
    			throw new IllegalArgumentException("Property 'transactionManager' is required");
    		}
    	}
    
    
    	@Override
    	@Nullable
    	public <T> T execute(TransactionCallback<T> action) throws TransactionException {
            // 判断 PlatformTransactionManager 不为空
    		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
    
            //
    		if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
    			return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
    		}
    		else {
    
                // 调用 platformTransactionManager.getTransaction(this),上边讲过 PlatformTransactionManager 的方法在 AbstractPlatformTransactionManager 都有实现
                // 遗留一:下边会讲 AbstractPlatformTransactionManager 这里不展开 只需要知道这里是创建了一个事务
    			TransactionStatus status = this.transactionManager.getTransaction(this);
    			T result;
    			try {
                    // 就是执行业务代码了
                    // 遗留二:下边会讲 TransactionCallback
    				result = action.doInTransaction(status);
    			}
    			catch (RuntimeException | Error ex) {
    				// Transactional code threw application exception -> rollback
                    // 事务回滚,方法就在下边,其实就是调了 platformTransactionManager.rollback 
                    // 遗留一
    				rollbackOnException(status, ex);
    				throw ex;
    			}
    			catch (Throwable ex) {
    				// Transactional code threw unexpected exception -> rollback
                    // 事务回滚 对未知异常做了封装
    				rollbackOnException(status, ex);
    				throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
    			}
                // 事务提交
                // 遗留一
    			this.transactionManager.commit(status);
    			return result;
    		}
    	}
    
    	/**
    	 * Perform a rollback, handling rollback exceptions properly.
    	 * @param status object representing the transaction
    	 * @param ex the thrown application exception or error
    	 * @throws TransactionException in case of a rollback error
    	 */
    	private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
    		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
    
    		logger.debug("Initiating transaction rollback on application exception", ex);
    		try {
                // 遗留一
    			this.transactionManager.rollback(status);
    		}
    		catch (TransactionSystemException ex2) {
    			logger.error("Application exception overridden by rollback exception", ex);
    			ex2.initApplicationException(ex);
    			throw ex2;
    		}
    		catch (RuntimeException | Error ex2) {
    			logger.error("Application exception overridden by rollback exception", ex);
    			throw ex2;
    		}
    	}
    
    
    	@Override
    	public boolean equals(Object other) {
    		return (this == other || (super.equals(other) && (!(other instanceof TransactionTemplate) ||
    				getTransactionManager() == ((TransactionTemplate) other).getTransactionManager())));
    	}
    
    }
    
    
    • 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
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169

    举一个我们项目使用 TransactionTemplate 的例子
    这里为什么要用 TransactionTemplate 是因为 @PostConstruct 注解上边加事务注解是不生效的。具体原因等讲完遗留一就明白了

        @PostConstruct
        public void init() {
            TransactionTemplate tmpl = new TransactionTemplate(jpaTransactionManager);
            tmpl.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    FwUserTokenInfo userTokenInfo = serviceAccountService.getServiceAccount();
                    AccessControlContext.setAcUser(userTokenInfo.getUser());
                    AccessControlDefaultPolicyUploader.super.init();
                }
            });
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    TransactionCallback

    这里先看遗留二吧,比较简单
    注释写的很清楚,事务代码的回调接口,与 TransactionTemplate 一起使用,通常作为方法实现中的匿名类

    /**
     * Callback interface for transactional code. Used with {@link TransactionTemplate}'s
     * {@code execute} method, often as anonymous class within a method implementation.
     *
     * <p>Typically used to assemble various calls to transaction-unaware data access
     * services into a higher-level service method with transaction demarcation. As an
     * alternative, consider the use of declarative transaction demarcation (e.g. through
     * Spring's {@link org.springframework.transaction.annotation.Transactional} annotation).
     *
     * @author Juergen Hoeller
     * @since 17.03.2003
     * @see TransactionTemplate
     * @see CallbackPreferringPlatformTransactionManager
     * @param <T> the result type
     */
    @FunctionalInterface
    public interface TransactionCallback<T> {
    
    	/**
    	 * Gets called by {@link TransactionTemplate#execute} within a transactional context.
    	 * Does not need to care about transactions itself, although it can retrieve and
    	 * influence the status of the current transaction via the given status object,
    	 * e.g. setting rollback-only.
    	 * <p>Allows for returning a result object created within the transaction, i.e. a
    	 * domain object or a collection of domain objects. A RuntimeException thrown by the
    	 * callback is treated as application exception that enforces a rollback. Any such
    	 * exception will be propagated to the caller of the template, unless there is a
    	 * problem rolling back, in which case a TransactionException will be thrown.
    	 * @param status associated transaction status
    	 * @return a result object, or {@code null}
    	 * @see TransactionTemplate#execute
    	 * @see CallbackPreferringPlatformTransactionManager#execute
    	 */
    	@Nullable
    	T doInTransaction(TransactionStatus status);
    
    }
    
    // 抽象方法实现了 TransactionCallback,我上边的例子其实就是使用了它
    /**
     * Simple convenience class for TransactionCallback implementation.
     * Allows for implementing a doInTransaction version without result,
     * i.e. without the need for a return statement.
     *
     * @author Juergen Hoeller
     * @since 28.03.2003
     * @see TransactionTemplate
     */
    public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {
    
    	@Override
    	@Nullable
    	public final Object doInTransaction(TransactionStatus status) {
    		doInTransactionWithoutResult(status);
    		return null;
    	}
    
    	/**
    	 * Gets called by {@code TransactionTemplate.execute} within a transactional
    	 * context. Does not need to care about transactions itself, although it can retrieve
    	 * and influence the status of the current transaction via the given status object,
    	 * e.g. setting rollback-only.
    	 * <p>A RuntimeException thrown by the callback is treated as application
    	 * exception that enforces a rollback. An exception gets propagated to the
    	 * caller of the template.
    	 * <p>Note when using JTA: JTA transactions only work with transactional
    	 * JNDI resources, so implementations need to use such resources if they
    	 * want transaction support.
    	 * @param status associated transaction status
    	 * @see TransactionTemplate#execute
    	 */
    	protected abstract void doInTransactionWithoutResult(TransactionStatus 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
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    AbstractPlatformTransactionManager

    遗留一, 这里比较重要了,注释也写得很清楚,是 Spring 处理事务的抽象基类,是具体平台事务的基础(也就是你想自定义一套事务管理最好以它为基础)
    直接看源码吧
    源码太长,分开看吧

    /**
     * Abstract base class that implements Spring's standard transaction workflow,
     * serving as basis for concrete platform transaction managers like
     * {@link org.springframework.transaction.jta.JtaTransactionManager}.
     *
     * <p>This base class provides the following workflow handling:
     * <ul>
     * <li>determines if there is an existing transaction;
     * <li>applies the appropriate propagation behavior;
     * <li>suspends and resumes transactions if necessary;
     * <li>checks the rollback-only flag on commit;
     * <li>applies the appropriate modification on rollback
     * (actual rollback or setting rollback-only);
     * <li>triggers registered synchronization callbacks
     * (if transaction synchronization is active).
     * </ul>
     *
     * <p>Subclasses have to implement specific template methods for specific
     * states of a transaction, e.g.: begin, suspend, resume, commit, rollback.
     * The most important of them are abstract and must be provided by a concrete
     * implementation; for the rest, defaults are provided, so overriding is optional.
     *
     * <p>Transaction synchronization is a generic mechanism for registering callbacks
     * that get invoked at transaction completion time. This is mainly used internally
     * by the data access support classes for JDBC, Hibernate, JPA, etc when running
     * within a JTA transaction: They register resources that are opened within the
     * transaction for closing at transaction completion time, allowing e.g. for reuse
     * of the same Hibernate Session within the transaction. The same mechanism can
     * also be leveraged for custom synchronization needs in an application.
     *
     * <p>The state of this class is serializable, to allow for serializing the
     * transaction strategy along with proxies that carry a transaction interceptor.
     * It is up to subclasses if they wish to make their state to be serializable too.
     * They should implement the {@code java.io.Serializable} marker interface in
     * that case, and potentially a private {@code readObject()} method (according
     * to Java serialization rules) if they need to restore any transient state.
     *
     * @author Juergen Hoeller
     * @since 28.03.2003
     * @see #setTransactionSynchronization
     * @see TransactionSynchronizationManager
     * @see org.springframework.transaction.jta.JtaTransactionManager
     */
    @SuppressWarnings("serial")
    public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
        // 对 这里就是给你看看注释,然后拜拜大神 Juergen Hoeller
    }
    
    
    • 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

    AbstractPlatformTransactionManager

    /*
     * @author Juergen Hoeller
     */
    @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
    	 */
    	@Override
    	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
            // do 开头。spring 中 do 开头的方法都是干实事的
    		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);
                    // 创建事务状态
    				DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                    // 开始事务
    				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);
    		}
    	}
    
    
        /**
    	 * This implementation of rollback handles participating in existing
    	 * transactions. Delegates to {@code doRollback} and
    	 * {@code doSetRollbackOnly}.
    	 * @see #doRollback
    	 * @see #doSetRollbackOnly
    	 */
    	@Override
    	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, false);
    	}
    
    	/**
    	 * Process an actual rollback.
    	 * The completed flag has already been checked.
    	 * @param status object representing the transaction
    	 * @throws TransactionException in case of rollback failure
    	 */
    	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();
    				}
    				else if (status.isNewTransaction()) {
    					if (status.isDebug()) {
    						logger.debug("Initiating transaction rollback");
    					}
    					doRollback(status);
    				}
    				else {
    					// 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);
    		}
    	}
    
    
    	/**
    	 * This implementation of commit handles participating in existing
    	 * transactions and programmatic rollback requests.
    	 * Delegates to {@code isRollbackOnly}, {@code doCommit}
    	 * and {@code rollback}.
    	 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
    	 * @see #doCommit
    	 * @see #rollback
    	 */
    	@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;
    		}
    
            // 全局事务 且被标记为需要回滚
    		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);
    	}
    
        /**
    	 * Process an actual commit.
    	 * Rollback-only flags have already been checked and applied.
    	 * @param status object representing the transaction
    	 * @throws TransactionException in case of commit failure
    	 */
    	private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    		try {
    			boolean beforeCompletionInvoked = false;
    
    			try {
    				boolean unexpectedRollback = false;
                    // 空方法,没找到实现
    				prepareForCommit(status);
                    // 事务提交前,触发回调
    				triggerBeforeCommit(status);
                    // 事务完成前,触发回调
    				triggerBeforeCompletion(status);
    				beforeCompletionInvoked = true;
    
    				if (status.hasSavepoint()) {
    					if (status.isDebug()) {
    						logger.debug("Releasing transaction savepoint");
    					}
    					unexpectedRollback = status.isGlobalRollbackOnly();
    					status.releaseHeldSavepoint();
    				}
                    // 是否是新事务,如果是新事务,将执行提交操作,比如传播行为是 REQUIRED 中嵌套了一个 REQUIRED,那么内部的事务就不是新的事务,外部的事务是新事务
    				else if (status.isNewTransaction()) {
    					if (status.isDebug()) {
    						logger.debug("Initiating transaction commit");
    					}
    					unexpectedRollback = status.isGlobalRollbackOnly();
                        // 提交事务
                        // 扩展一
    					doCommit(status);
    				}
    				else if (isFailEarlyOnGlobalRollbackOnly()) {
    					unexpectedRollback = status.isGlobalRollbackOnly();
    				}
    
    				// Throw UnexpectedRollbackException if we have a global rollback-only
    				// marker but still didn't get a corresponding exception from commit.
    				if (unexpectedRollback) {
    					throw new UnexpectedRollbackException("Transaction silently rolled back because it has been marked as rollback-only");
    				}
    			}
    			catch (UnexpectedRollbackException ex) {
    				// can only be caused by doCommit
                    // 事务完成之后,执行一些回调
    				triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
    				throw ex;
    			}
    			catch (TransactionException ex) {
    				// can only be caused by doCommit
                    // 提交过程中有异常,执行回滚操作
    				if (isRollbackOnCommitFailure()) {
    					doRollbackOnCommitException(status, ex);
    				}
    				else {
                        // 事务完成之后,执行一些回调
    					triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
    				}
    				throw ex;
    			}
    			catch (RuntimeException | Error ex) {
    				if (!beforeCompletionInvoked) {
    					triggerBeforeCompletion(status);
    				}
                    // 提交过程中有异常,执行回滚操作
    				doRollbackOnCommitException(status, ex);
    				throw ex;
    			}
    
    			// Trigger afterCommit callbacks, with an exception thrown there
    			// propagated to callers but the transaction still considered as committed.
    			try {
                    // 事务 commit 之后,执行一些回调
    				triggerAfterCommit(status);
    			}
    			finally {
                    // 事务完成之后,执行一些回调
    				triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
    			}
    
    		}
    		finally {
                // 事务执行完毕之后,执行一些清理操作
    			cleanupAfterCompletion(status);
    		}
    	}
    
    	private void cleanupAfterCompletion(DefaultTransactionStatus status) {
            // 将事务状态置为已完成
    		status.setCompleted();
            // 是否是新的事务同步
    		if (status.isNewSynchronization()) {
                // 扩展二 清空当前线程 ThreadLocal 里边的所有东西
    			TransactionSynchronizationManager.clear();
    		}
            // 是否是新的事务
    		if (status.isNewTransaction()) {
                // 提交事务并清理
    			doCleanupAfterCompletion(status.getTransaction());
    		}
            // 当前事务状态是否被挂起
    		if (status.getSuspendedResources() != null) {
    			if (status.isDebug()) {
    				logger.debug("Resuming suspended transaction after completion of inner transaction");
    			}
    			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
                // 恢复被挂起的事务
    			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
    		}
    	}
    
        // 抽象方法,所以还要往下走
        // 该方法作用:返回当前事务的事务状态
        // 它的实现有很多,但里边的逻辑都差不多,毕竟只是拿到当前事务状态:CciLocalTransactionManager DataSourceTransactionManager HibernateTransactionManager JpaTransactionManager JtaTransactionManager...
        // 扩展一:找一个实现看一下
        protected abstract Object doGetTransaction() throws TransactionException;
    
        // 扩展一
        protected abstract void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException;
    
        // 扩展一
    	protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
    
        // 扩展一
        protected void doCleanupAfterCompletion(Object transaction) {};
    
        // 扩展一
        protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
    
    }
    
    // 扩展一
    public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
    
        protected Object doGetTransaction() {
            // 构造了个 DataSourceTransactionObject 对象,对象里边没啥就俩字段:private boolean newConnectionHolder;和 private boolean mustRestoreAutoCommit;
            DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
            // 默认是false:private boolean nestedTransactionAllowed = false; 表示是否允许嵌套事务
            txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
            // 这一个是核心,无论哪种实现都需要调这个方法,区别只是结果做了强转
            // 这里需要注意一点就是入参传入的是 DataSource 对象,然后返回当前线程资源的持有者 ConnectionHolder,后期连接归 ConnectionHolder 管 
            // 扩展二
            ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.obtainDataSource());
            // 将 conHolder 丢到 DataSourceTransactionObject 中,第二个参数表示是否是一个新的连接,这里肯定为 false,因为通过 datasource 获取的连接才是新的连接
            txObject.setConnectionHolder(conHolder, false);
            return txObject;
        }
    
        protected DataSource obtainDataSource() {
            DataSource dataSource = this.getDataSource();
            Assert.state(dataSource != null, "No DataSource set");
            return dataSource;
        }
    
        @Nullable
        public DataSource getDataSource() {
            return this.dataSource;
        }
    
        /**
    	 * This implementation sets the isolation level but ignores the timeout.
    	 */
    	@Override
    	protected void doBegin(Object transaction, TransactionDefinition definition) {
            // 强转成 DataSource 事务对象
    		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    		Connection con = null;
    
    		try {
    			if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                    // 获取一个事务的连接
    				Connection newCon = obtainDataSource().getConnection();
    				if (logger.isDebugEnabled()) {
    					logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
    				}
                    // 将事务的连接放到 DataSourceTransactionObject 对象中,并标记为新的连接
    				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
    			}
    
                // 标记事务连接为 true
    			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
                // 获取事务的连接
    			con = txObject.getConnectionHolder().getConnection();
    
                // 获取事务的隔离级别,并赋值。实现比较简单不展开了
                // 这里边其实做了两件事:(1)// Set read-only flag; (2)// Apply specific isolation level, if any.
    			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
    			txObject.setPreviousIsolationLevel(previousIsolationLevel);
    
    			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
    			// so we don't want to do it unnecessarily (for example if we've explicitly
    			// configured the connection pool to set it already).
    			if (con.getAutoCommit()) {
    				txObject.setMustRestoreAutoCommit(true);
    				if (logger.isDebugEnabled()) {
    					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
    				}
                    // 改为不自动提交
    				con.setAutoCommit(false);
    			}
    
                // 设置 TransactionSynchronizationManager 中的一些变量值
    			prepareTransactionalConnection(con, definition);
                // 设置来连接对象可用
    			txObject.getConnectionHolder().setTransactionActive(true);
    
    			int timeout = determineTimeout(definition);
    			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                    // 设置连接对象的超时时间
    				txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
    			}
    
    			// Bind the connection holder to the thread.
                // 核心方法!!! 绑定线程!!!
    			if (txObject.isNewConnectionHolder()) {
                    // 扩展二
    				TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
    			}
    		}
    
    		catch (Throwable ex) {
    			if (txObject.isNewConnectionHolder()) {
    				DataSourceUtils.releaseConnection(con, obtainDataSource());
    				txObject.setConnectionHolder(null, false);
    			}
    			throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
    		}
    	}
    
    	@Override
    	protected void doCommit(DefaultTransactionStatus status) {
            // 获取当前线程对象
    		DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    		// 获取当前连接
            Connection con = txObject.getConnectionHolder().getConnection();
    		if (status.isDebug()) {
    			logger.debug("Committing JDBC transaction on Connection [" + con + "]");
    		}
    		try {
                // 提交事务 具体不展开了 
    			con.commit();
    		}
    		catch (SQLException ex) {
    			throw new TransactionSystemException("Could not commit JDBC transaction", ex);
    		}
    	}
    
    	@Override
    	protected void doCleanupAfterCompletion(Object transaction) {
    		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    
    		// Remove the connection holder from the thread, if exposed.
    		if (txObject.isNewConnectionHolder()) {
                // 解绑资源,对应前边的 bindResource,就是在 ThreadLocal 里边删掉资源
    			TransactionSynchronizationManager.unbindResource(obtainDataSource());
    		}
    
    		// Reset connection.
            // 重置连接
    		Connection con = txObject.getConnectionHolder().getConnection();
    		try {
    			if (txObject.isMustRestoreAutoCommit()) {
    				con.setAutoCommit(true);
    			}
    			DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
    		}
    		catch (Throwable ex) {
    			logger.debug("Could not reset JDBC Connection after transaction", ex);
    		}
    
    		if (txObject.isNewConnectionHolder()) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
    			}
    			DataSourceUtils.releaseConnection(con, this.dataSource);
    		}
    
            // 清理事务
    		txObject.getConnectionHolder().clear();
    	}
    
    	@Override
    	protected void doRollback(DefaultTransactionStatus status) {
    		DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    		Connection con = txObject.getConnectionHolder().getConnection();
    		if (status.isDebug()) {
    			logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
    		}
    		try {
                // 回滚 具体不展开了 
    			con.rollback();
    		}
    		catch (SQLException ex) {
    			throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
    		}
    	}
    
    }
    
    // 扩展二
    // 这也是一个比较核心的抽象类
    public abstract class TransactionSynchronizationManager {
    
        // 存储事务资源信息
        private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
    
        // 存储事务过程中的一些回调接口(TransactionSynchronization接口,这个可以在事务的过程中给开发者提供一些回调用的)
    	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
    
        // 存储当前正在运行的事务的名称
    	private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name");
    
        // 存储当前正在运行的事务是否是只读的
     	private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>("Current transaction read-only status");
    
        // 存储当前正在运行的事务的隔离级别
    	private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>("Current transaction isolation level");
    
        // 存储当前正在运行的事务是否是活动状态,事务启动的时候会被激活
    	private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<>("Actual transaction active");
    
    	/**
    	 * Retrieve a resource for the given key that is bound to the current thread.
    	 * @param key the key to check (usually the resource factory)
    	 * @return a value bound to the current thread (usually the active
    	 * resource object), or {@code null} if none
    	 * @see ResourceTransactionManager#getResourceFactory()
    	 */
        // 返回当前线程的资源持有者
    	@Nullable
    	public static Object getResource(Object key) {
            // 扩展三 最后都是调用了扩展三的代码,获取 DataSource 的 bean
    		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
            // 获取连接对象 
    		Object value = doGetResource(actualKey);
    		if (value != null && logger.isTraceEnabled()) {
    			logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
    		}
    		return value;
    	}
    
    	/**
    	 * Actually check the value of the resource that is bound for the given key.
    	 */
    	@Nullable
    	private static Object doGetResource(Object actualKey) {
    		Map<Object, Object> map = resources.get();
    		if (map == null) {
                // 最开始必然走这里,因为没 put 进 resources
    			return null;
    		}
    		Object value = map.get(actualKey);
    		// Transparently remove ResourceHolder that was marked as void...
    		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
    			map.remove(actualKey);
    			// Remove entire ThreadLocal if empty...
    			if (map.isEmpty()) {
    				resources.remove();
    			}
    			value = null;
    		}
    		return value;
    	}
    
    	/**
    	 * Bind the given resource for the given key to the current thread.
    	 * @param key the key to bind the value to (usually the resource factory)
    	 * @param value the value to bind (usually the active resource object)
    	 * @throws IllegalStateException if there is already a value bound to the thread
    	 * @see ResourceTransactionManager#getResourceFactory()
    	 */
    	public static void bindResource(Object key, Object value) throws IllegalStateException {
            // 获取当前线程
    		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
    		Assert.notNull(value, "Value must not be null");
    		Map<Object, Object> map = resources.get();
    		// set ThreadLocal Map if none found
    		if (map == null) {
    			map = new HashMap<>();
                // 更新到 ThreadLocal 中
    			resources.set(map);
    		}
    		Object oldValue = map.put(actualKey, value);
    		// Transparently suppress a ResourceHolder that was marked as void...
    		if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
    			oldValue = null;
    		}
    		if (oldValue != null) {
    			throw new IllegalStateException("Already value [" + oldValue + "] for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
    		}
    		if (logger.isTraceEnabled()) {
    			logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" + Thread.currentThread().getName() + "]");
    		}
    	}
    
    	/**
    	 * Clear the entire transaction synchronization state for the current thread:
    	 * registered synchronizations as well as the various transaction characteristics.
    	 * @see #clearSynchronization()
    	 * @see #setCurrentTransactionName
    	 * @see #setCurrentTransactionReadOnly
    	 * @see #setCurrentTransactionIsolationLevel
    	 * @see #setActualTransactionActive
    	 */
        public static void clear() {
    		synchronizations.remove();
    		currentTransactionName.remove();
    		currentTransactionReadOnly.remove();
    		currentTransactionIsolationLevel.remove();
    		actualTransactionActive.remove();
    	}
    
    }
    
    // 扩展三
    public class DefaultScopedObject implements ScopedObject, Serializable {
    
    	private final ConfigurableBeanFactory beanFactory;
    
    	private final String targetBeanName;
    
    
    	/**
    	 * Creates a new instance of the {@link DefaultScopedObject} class.
    	 * @param beanFactory the {@link ConfigurableBeanFactory} that holds the scoped target object
    	 * @param targetBeanName the name of the target bean
    	 */
    	public DefaultScopedObject(ConfigurableBeanFactory beanFactory, String targetBeanName) {
    		Assert.notNull(beanFactory, "BeanFactory must not be null");
    		Assert.hasText(targetBeanName, "'targetBeanName' must not be empty");
    		this.beanFactory = beanFactory;
    		this.targetBeanName = targetBeanName;
    	}
    
    
    	@Override
    	public Object getTargetObject() {
    		return this.beanFactory.getBean(this.targetBeanName);
    	}
    
    	@Override
    	public void removeFromScope() {
    		this.beanFactory.destroyScopedBean(this.targetBeanName);
    	}
    
    }
    
    
    • 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
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659

    响应式事务

    未完待续。。。

  • 相关阅读:
    mybatis-plus代码生成工具
    伺服驱动器的位置控制模块电路原理是什么?
    c语言练习87:合并两个有序数组
    【MATLAB】史上最全的5种数据插值算法全家桶
    统计学习笔记第 1 部分:Hoeffding 的不等式推导与模拟
    C++ 数据结构--二叉搜索树的实现
    Jmeter 的使用
    ATF安全漏洞挖掘之FUZZ测试
    Flink1.14新特性介绍及尝鲜
    PTA题目 奇偶分家
  • 原文地址:https://blog.csdn.net/lbh_paopao/article/details/125545642