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之不得不了解的内容——AOP概念篇
第十三章 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版)》
在 第一部分 中, A君 在 自己的努力下,实现了一个简单的 IOC容器。虽然相较于 Spring,犹如寒鸦配鸾凤。不过通过自己努力得来,绝不是拿来即用能够比拟的。在 IOC篇 完结后, A君 将会开启新的篇章——AOP篇
尝试动手写IOC容器
出场人物:A君(苦逼的开发)、老大(项目经理)
背景:老大要求A君在一周内开发个简单的 IOC容器
前情提要: A君 在 老大 的鞭策下,终于磕磕绊绊的实现了一个简单的 IOC容器 。。。
AOP?真的不熟啊
在 A君 完成 IOC 部分,确实清闲过一段时间,今天一早就看到 老大 出去了,这摸鱼简直爽到飞起。俗话说:乐极生悲,正当 A君 忘乎所以的时候,老大 笑眯眯的回来了,径直走到 A君 的身边。满脸笑意的开口到:“A君 最近手头有事吗?”
老大 一笑,生死难料。A君 咯噔一下,心想:好日子要到头了。嘴上回道:“手头的事做的差不多了。”
“那正好,今天去客户那里,客户要求在 IOC容器 上,添加 AOP 这部分功能,你这几天先准备准备。” 老大 说完,也不等 A君 回答,就飘然而去
看着 老大 那欢快的背影。 A君 心里暗忖:“看来这单值不少钱呢!” 回过神来,A君 一阵头大,AOP 平时他也有用过,只是要自己写出来,那是想都不曾想过的事。一想到:连接点、切点、通知、切面 等专业名词,还要实现它们。A君 不经叫苦不迭
上边一张嘴,下边跑断腿。A君 这几天四处翻博客看,看的头昏脑涨。始终对 AOP 没有个系统性的认识,网上基本都是说日志、事务等例子,但是 A君 感觉明明用 继承 也能实现,为什么一定要用 AOP?为此,A君 决定写了个简单的例子,就以日志和统计方法执行时间例子,A君 先定义一个 Base 抽象类,用来实现日志,耗时等功能,如下:
public abstract class Base {
protected void log() {
Class<? extends Base> clazz = this.getClass();
if (clazz == OOPComputer.class) {
System.out.println("输出电脑日志 ##########");
} else if (clazz == OOPTable.class) {
System.out.println("输出桌子日志 ##########");
} else {
System.out.println("输出其他日志 ##########");
}
}
public void invoke() {
log();
long start = System.currentTimeMillis();
doSomething();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "ms");
}
protected abstract void doSomething();
}
而后添加一个简单的 OOPComputer 实现类,如下:
public class OOPComputer extends Base {
@Override
protected void doSomething() {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("我是电脑");
}
}
做好准备后,A君 写了个简单的测试,如下:
import com.hqd.test.temp.oop.OOPComputer;
import org.junit.Test;
public class OOPTest {
@Test
public void oop() {
OOPComputer computer = new OOPComputer();
computer.invoke();
}
}
这么一写,从结果来看 OOP(面向对象) 貌似也能实现 AOP 相同的结果。不过 A君 看出了点端倪:
- JAVA 是单继承的,这样子写的话,所有类必须强制实现 Base 类,后续子类如有需要继承其他类怎么办?
- 现在开发基本不可能是从无到有,如果存在存量代码,这样的改造量相当的恐怖
- 日志和耗时本来是两个不同的功能,按照单一性原则,它们应该是分属两个不同的模块,现在强行将它们耦合在一起,后续在加上事务、权限呢?只会导致 Base 类越来越臃肿,最终导致 屎山代码
- 各个模块功能不一定有关联,现在强制继承同一个基础类,从设计的角度来看怪怪的,会让设计趋于僵化
如此一来,A君 再去看那些文章,就不像之前那么懵懂了。既然明白了 OOP(面向对象) 的局限性,那么回过头来再看 AOP 的概念就能明白它的用途了。维基百科对 AOP 的描述如下:
面向方面编程将代码逻辑切分为不同的模块(即关注,一段特定的逻辑功能)。几乎所有的编程思想都涉及代码功能的分类,将各项关注(concern)封装成独立的抽象模块(如函数、过程、模块、类以及方法等),后者又可供进一步实现、封装和重写。部分关注“交叉切入”程序代码中的数个模块,即在多个模块中都有出现,它们即被称作交叉切入关注
日志功能即是交叉切入关注的一个典型案例,因为日志功能往往跨越系统中的每个业务模块,即交叉切入(crosscut)所有有日志需求的类及方法体。而对于一个信用卡应用程序来说,存款、取款、帐单管理是它的核心关注,日志和持久化将成为交叉切入整个对象结构的交叉切入关注
说实话,还是觉得拗口,怎么读这么怪。没办法,概念性的东西就是如此,不懂的人看了还是不懂。A君 索性也不去咬文嚼字了,任何技术或者思想都是为了方便人们的工作, 先记住 AOP 是对 OOP(面向对象) 的补充,AOP 旨在少改代码,去实现一些公共的功能就行了
总结
正所谓树欲静而风不止,欲知后事如何,请看下回分解(✪ω✪)