Spring源码阅读目录
第一部分——IOC篇
第一章 Spring之最熟悉的陌生人——IOC
第二章 Spring之假如让你来写IOC容器——加载资源篇
第三章 Spring之假如让你来写IOC容器——解析配置文件篇
第四章 Spring之假如让你来写IOC容器——XML配置文件篇
第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean
第六章 Spring之假如让你来写IOC容器——Scope和属性填充
第七章 Spring之假如让你来写IOC容器——属性填充特别篇:SpEL表达式
第八章 Spring之假如让你来写IOC容器——拓展篇
第九章 Spring之源码阅读——环境搭建篇
第十章 Spring之源码阅读——IOC篇
第二部分——AOP篇
第十一章 Spring之不太熟的熟人——AOP
第十二章 Spring之不得不了解的内容——概念篇
第十三章 Spring之假如让你来写AOP——AOP联盟篇
第十四章 Spring之假如让你来写AOP——雏形篇
第十五章 Spring之假如让你来写AOP——Joinpoint(连接点)篇
第十六章 Spring之假如让你来写AOP——Pointcut(切点)篇
第十七章 Spring之假如让你来写AOP——Advice(通知)上篇
第十八章 Spring之假如让你来写AOP——Advice(通知)下篇
第十九章 Spring之假如让你来写AOP——番外篇:Spring早期设计
第二十章 Spring之假如让你来写AOP——Aspect(切面)篇
第二十一章 Spring之假如让你来写AOP——Weaver(织入器)篇
第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇
第二十三章 Spring之假如让你来写AOP——融入IOC容器篇
第二十四章 Spring之源码阅读——AOP篇
第三部分——事务篇
第二十五章 Spring之曾经的老朋友——事务
第二十六章 Spring之假如让你来写事务——初稿篇
第二十七章 Spring之假如让你来写事务——铁三角篇
第二十八章 Spring之假如让你来写事务——属性篇
第二十九章 Spring之假如让你来写事务——状态篇
第三十章 Spring之假如让你来写事务——管理篇
第三十一章 Spring之假如让你来写事务——融入IOC容器篇
第三十二章 Spring之源码阅读——事务篇
第四部分——MVC篇
第三十三章 Spring之梦开始的地方——MVC
第三十四章 Spring之假如让你来写MVC——草图篇
第三十五章 Spring之假如让你来写MVC——映射器篇
第三十六章 Spring之假如让你来写MVC——拦截器篇
第三十七章 Spring之假如让你来写MVC——控制器篇
第三十八章 Spring之假如让你来写MVC——适配器篇
第三十九章 Spring之假如让你来写MVC——番外篇:类型转换
第四十章 Spring之假如让你来写MVC——ModelAndView篇
第四十一章 Spring之假如让你来写MVC——番外篇:数据绑定
第四十二章 Spring之假如让你来写MVC——视图篇
第四十三章 Spring之假如让你来写MVC——上传文件篇
第四十四章 Spring之假如让你来写MVC——异常处理器篇
第四十五章 Spring之假如让你来写MVC——国际化篇
第四十六章 Spring之假如让你来写MVC——主题解析器篇
第四十七章 Spring之假如让你来写MVC——闪存管理器篇
第四十八章 Spring之假如让你来写MVC——请求映射视图篇
第四十九章 Spring之假如让你来写MVC——番外篇:属性操作
第五十章 Spring之假如让你来写MVC——融入IOC容器篇
第五十一章 Spring之源码阅读——MVC篇
第五部分——Boot篇
第五十二章 Spring之再进一步——Boot
第五十三章 Spring之假如让你来写Boot——环境篇
第五十四章 Spring之假如让你来写Boot——注解篇(上)
第五十五章 Spring之假如让你来写Boot——注解篇(下)
第五十六章 Spring之假如让你来写Boot——SPI篇
第五十七章 Spring之假如让你来写Boot——配置文件篇(上)
第五十八章 Spring之假如让你来写Boot——配置文件篇(下)
第五十九章 Spring之假如让你来写Boot——番外篇:再谈Bean定义
第六十章 Spring之假如让你来写Boot——自动装配篇
第六十一章 Spring之假如让你来写Boot——番外篇:杂谈Starter
第六十二章 Spring之假如让你来写Boot——番外篇:重构BeanFactory
第六十三章 Spring之假如让你来写Boot——番外篇:再谈ApplicationContext
第六十四章 Spring之假如让你来写Boot——内嵌Web容器篇
第六十五章 Spring之假如让你来写Boot——Main方法启动篇
第六十六章 Spring之最终章——结语篇
文章目录
前言
对于Spring一直都是既熟悉又陌生,说对它熟悉吧,平时用用没啥问题,但面试的时候被问的一脸懵逼,就很尴尬,都不好意思在简历上写着熟悉Spring了
所以决定花点时间研究研究Spring的源码。主要参考的书籍是:《Spring源码深度解析(第2版)》、《Spring揭秘》、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》
书接上回,在上篇 第二十九章 Spring之假如让你来写事务——状态篇 中,A君 实现了 事务状态,完成了铁三角之二。接下来看看 A君 会有什么骚操作吧
尝试动手写IOC容器
出场人物:A君(苦逼的开发)、老大(项目经理)
背景:老大要求A君在一周内开发个简单的 IOC容器
前情提要:A君 实现了 事务状态,完成了铁三角之二 。。。
第二十八版 事务管理器
前几天,A君 已经完成了铁三角中的 事务属性、事务状态。这两个简直不要太简单,整的 A君 都有些飘飘然了,以为 事务管理器 也会这么简单。结果一看,傻眼了,没想到 事务管理器 才是真正复杂的点,前面那两个简直不值一提,小巫见大巫。A君 梳理了下逻辑,所谓 管理器,其实就是控制 事务 提交,或者是回滚
在经过前边一系列的洗礼,A君 已经习惯性的思考是否可以提取抽象类了,这么一琢磨,还真有。在整个 事务 的执行过程中,在各个阶段,需要调用对应的回调,亦或是检查是否超时,以及根据传播行为来判断是否需要创建新 事务,或者是暂停 事务,这部分逻辑都是可以提取出来。规定流程,不能实现的交给子类。模板模式!A君 心里凛然,果然设计模式无处不在啊。接下来,就是应该考虑从哪个开始,无论是提交还是回滚,这两个操作的前提,是 事务状态 和 事务属性,如果 事务 是只读的,则 事务 无法提交,如果 事务 以完成,则应该抛出异常。不过,在此之前,得需要了解下 事务传播行为。所谓 事务传播 其实就是为了满足不同业务场景下的需要,比如说嵌套事务、子事务等。具体如下:
- REQUIRED(默认传播行为):如果当前存在事务,使用当前事务;如果没有事务,则新建一个事务。适合大多数情况,方法间需要共享一个事务
- REQUIRES_NEW:总是新建一个事务。如果当前存在事务,挂起当前事务。新事务与原事务相互独立,互不影响
- SUPPORTS:如果当前存在事务,使用事务;如果没有事务,则以非事务方式运行。适合需要支持事务但不强制要求事务的情况
- NOT_SUPPORTED:总是以非事务方式运行。如果当前存在事务,挂起事务。适用于不需要事务的情况
- MANDATORY:当前必须存在事务,如果没有事务,则抛出异常。强制调用者必须在事务上下文中
- NEVER:当前必须没有事务运行,否则抛出异常。强制以非事务方式运行
- NESTED:如果当前存在事务,则嵌套事务运行(使用保存点机制,嵌套事务可以回滚到保存点,不会影响外部事务)。如果没有事务,则新建一个事务
好,做足功课后,A君 准备撸代码了。定义 AbstractPlatformTransactionManager
类,实现 getTransaction
方法,代码如下:
public final TransactionStatus getTransaction(TransactionDefinition definition) {
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
/**
* 获取事务对象
*/
Object transaction = doGetTransaction();
/**
* 存在事务,检查事务传播行为
* 子类实现,各个具体实现不一
*/
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(def, transaction);
}
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new RuntimeException("Invalid transaction timeout:" + def.getTimeout());
}
/**
* 如果当前存在事务,则加入当前事务;如果当前没有事务,则抛出异常
*/
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new RuntimeException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
} else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
/**
* 暂停事务
*/
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
return startTransaction(def, transaction, suspendedResources);
} catch (RuntimeException | Error ex) {
/**
* 恢复事务
*/
resume(null, suspendedResources);
throw ex;
}
} else {
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, null);
}
}
整体流程 A君 大概捋了出来,但是有点小问题,怎么暂停,怎么恢复?暂停时需要把当前信息保存到某个对象当中,不然到时候恢复都不知道要恢复什么了。A君 定义 SuspendedResourcesHolder
类,代码如下:
/**
* 悬挂事务信息保存
*/
protected static final class SuspendedResourcesHolder {
/**
* 事务信息
*/
private final Object suspendedResources;
/**
* 同步器
*/
private List<TransactionSynchronization> suspendedSynchronizations;
private String name;
private boolean readOnly;
/**
* 隔离级别
*/
private Integer isolationLevel;
/**
* 是否活跃
*/
private boolean wasActive;
private SuspendedResourcesHolder(Object suspendedResources) {
this.suspendedResources = suspendedResources;
}
private SuspendedResourcesHolder(
Object suspendedResources, List<TransactionSynchronization> suspendedSynchronizations,
String name, boolean readOnly, Integer isolationLevel, boolean wasActive) {