Commit 8b079d43 by SunWei峰

基本掌握事务

parent db94ff19
......@@ -44,3 +44,9 @@ atlassian-ide-plugin.xml
# VS Code
.vscode/
# osfung configuration
../.idea
import-into-eclipse.md
import-into-idea.md
CONTRIBUTING.md
\ No newline at end of file
# <img src="src/docs/spring-framework.png" width="80" height="80"> Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-5.3.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring)
# Spring源码分析
***
> 说明: 个人学习 Spring 源码,仅供自己学习使用,其中不以任何方式谋取利益,
> 有需要的同学们可以自行下载。
> 学习过程可能引用到某些博客中的信息,书籍中的信息。
> 如果涉嫌侵权,请联系本人立即删除。
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
`联系邮箱``osfung@163.com`
## Code of Conduct
参考书籍:《Spring 源码深度解析》
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
源码获取方式:github 官方获取
## Access to Binaries
Spring版本:6.0.0
For access to artifacts or a distribution zip, see the [Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts) wiki page.
## Documentation
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](src/docs/asciidoc)), Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Micro-Benchmarks
See the [Micro-Benchmarks](https://github.com/spring-projects/spring-framework/wiki/Micro-Benchmarks) Wiki page.
## Build from Source
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) Wiki page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
## Continuous Integration Builds
Information regarding CI builds can be found in the [Spring Framework Concourse pipeline](ci/README.adoc) documentation.
## Stay in Touch
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [news feed](https://spring.io/blog/category/news).
## License
The Spring Framework is released under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0).
Java版本:JDK17
\ No newline at end of file
......@@ -373,12 +373,16 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
private <T> T execute(StatementCallback<T> action, boolean closeResources) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
// 从数据源中获取数据连接。
Connection con = DataSourceUtils.getConnection(obtainDataSource());
Statement stmt = null;
try {
// 创建 Statement。
stmt = con.createStatement();
applyStatementSettings(stmt);
// 回调执行个性化业务
T result = action.doInStatement(stmt);
// 警告处理
handleWarnings(stmt);
return result;
}
......@@ -386,6 +390,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
// 释放数据库连接,避免当异常转换器没有被初始化的时候出现潜在的连接池死锁
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
......@@ -1457,10 +1462,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
* @see org.springframework.jdbc.datasource.DataSourceUtils#applyTransactionTimeout
*/
protected void applyStatementSettings(Statement stmt) throws SQLException {
// 设置 fetchSize 属性
// 一次性 result.next() 的时候,请求多少条数据
int fetchSize = getFetchSize();
if (fetchSize != -1) {
stmt.setFetchSize(fetchSize);
}
// 设置 maxRows 属性
// 结果集返回最大行数
int maxRows = getMaxRows();
if (maxRows != -1) {
stmt.setMaxRows(maxRows);
......
......@@ -241,7 +241,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
// 是否允许设置保存点:决定是否允许嵌套事务的存在
// 是否允许设置保存点
txObject.setSavepointAllowed(isNestedTransactionAllowed());
// 如果当前线程已经记录了数据库连接则使用原有连接
ConnectionHolder conHolder =
......
......@@ -102,24 +102,34 @@ public abstract class DataSourceUtils {
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource, "No DataSource specified");
// 获取当前线程的数据库连接持有者。这里是事务中的连接时同一个db连接
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
// 如果存在持有者 && (存在连接 || 和事务同步状态)
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
// 标记引用次数加一
conHolder.requested();
// 如果当前线程存在持有者,并且与事务同步了,如果仍然没有DB 连接,那么说明当前线程就是不存在数据库连接,则获取连接绑定到持有者上。
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
// 持有者不存在连接则获取连接
conHolder.setConnection(fetchConnection(dataSource));
}
// 返回持有者所持有的连接
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
// 到这里没返回,则说明 没有持有者 || 持有者没有同步绑定
logger.debug("Fetching JDBC Connection from DataSource");
// 获取到 DB 连接
Connection con = fetchConnection(dataSource);
// 如果当前线程的事务同步处于活动状态
if (TransactionSynchronizationManager.isSynchronizationActive()) {
try {
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
// 如果持有者为 null 则创建一个,否则将刚才创建的 DB 连接赋值给持有者
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
......@@ -127,7 +137,9 @@ public abstract class DataSourceUtils {
else {
holderToUse.setConnection(con);
}
// 记录数据库连接: 引用次数加1
holderToUse.requested();
// 设置事务和持有者同步
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse, dataSource));
holderToUse.setSynchronizedWithTransaction(true);
......
......@@ -141,8 +141,7 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
// 这里是 SpringTransactionAnnotationParser 类型,SpringTransactionAnnotationParser#isCandidateClass
// 中判断了目标类是否存在 org.springframework.transaction.annotation.Transactional 注解
// 中判断了目标类是否可以加 org.springframework.transaction.annotation.Transactional 注解
if (parser.isCandidateClass(targetClass)) {
return true;
}
......
......@@ -45,8 +45,13 @@ public class ProxyTransactionManagementConfiguration extends AbstractTransaction
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
// pointcut属性:final 属性直接new的,其中重写了 getTransactionAttributeSource(),返回 set 进去的 transactionAttributeSource
// new 的时候会直接 setClassFilter,自己的内部类。
// 一个是自己直接 matches(),一个是 getClassFilter().matches()
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
......@@ -58,6 +63,7 @@ public class ProxyTransactionManagementConfiguration extends AbstractTransaction
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// 提供注解的解析和缓存,以及是否 cutPoint 的 matches() 的真实逻辑
// Accept protected @Transactional methods on CGLIB proxies, as of 6.0.
return new AnnotationTransactionAttributeSource(false);
}
......@@ -66,6 +72,7 @@ public class ProxyTransactionManagementConfiguration extends AbstractTransaction
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
// 主要定义了 invoke 方法
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
......
......@@ -176,7 +176,7 @@ public abstract class AbstractFallbackTransactionAttributeSource
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
// 寻找实现类方法的事务属性,即类方法判断是否有声明事务属性并解析注解
// 寻找实现类方法的事务属性,即 类方法判断是否有声明事务属性并解析注解
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
......
......@@ -385,7 +385,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
// 判断 tm 是否是 PlatformTransactionManager 类型,是则强转,不是则抛出异常
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 构造方法的唯一标识(全路径了类名.方法)
// 构造方法的唯一标识(全路径了类名.方法,或者是 TransactionAttribute 的描述信息)
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 4. 对不同事务情景的处理
// 声明式事务的处理
......@@ -618,7 +618,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 获取事务的 TransactionStatus
// 获取事务的 TransactionStatus,并根据规则开启新事务
status = tm.getTransaction(txAttr);
}
else {
......
......@@ -43,7 +43,7 @@ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPoi
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 调用 TransactionAttributeSource.getTransactionAttribute方法来匹配
// 调用 TransactionAttributeSource.getTransactionAttribute 方法来匹配
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
......
......@@ -349,7 +349,8 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 2. 判断当前线程是否存在事务,判断依据是当前线程记录的数据库连接不为空,且连接(connectionHolder)中的 transactionActive 属性 为true;
// 2. 判断当前线程是否存在事务,判断依据是当前线程记录的
// 数据库连接(connectionHolder)不为空,且连接中的 transactionActive 属性 为true;
// 这个方法的实现在 DataSourceTransactionManager # isExistingTransaction。
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
......@@ -413,6 +414,9 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
// 创建一个默认的 DefaultTransactionStatus
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 接下来的两步就是设置 DataSourceTransactionObject、绑定到当前线程的 ThreadLocal
// 构造 Transaction,包括设置 ConnectionHolder、隔离级别、timeout。
// 并且如果是新连接,则绑定当当前线程。
doBegin(transaction, definition);
......
......@@ -73,21 +73,26 @@ import org.springframework.util.Assert;
*/
public abstract class TransactionSynchronizationManager {
// 保存连接资源,因为一个方法里面可能包含两个事务(比如事务传播特性为:TransactionDefinition#PROPAGATION_REQUIRES_NEW),所以就用 Map 来保存资源.
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
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");
// 用于保存当前事务是否还是 Active 状态
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment