学习过程
学习Springframework6.0.8,前后将近4个月终于结束了。学习主要内容如图(红框):
本次学习主要针对核心模块:Beans、Context、Core、SpEL(完全独立于框架的,没深入学习)、AOP,以SF应用的初始化过程为轴线,较深入了解了Spring的核心技术dependency injection, events, resources, i18n, validation, data binding, type conversion, SpEL, AOP。
学习方法总结
1、采用应用跟踪方法为主,即编写最简单应用,然后以应用容器ClassPathApplicationContext初始化为起点,跟踪初始化全过程:容器初始化、加载资源、加载Bean定义及Bean初始化;同时把初始化过程同各个技术结合点入手,跟进具体技术如何实现。个人认为这种方法最有效的特点就是实现和结果印证,有助于对框架的理解。
2、学习过程中仅仅看源码是远远不够,还需要到做如下几点:
2.1 用UML工具画类关系图,这样才容易建立相关点的整体印象。
2.2 画关键过程的时序图,有助于清晰执行过程及跳转关系。
2.3 做笔记,可以文档形式或博客形式。特别是源码逐行注释非常有助于理解框架。
2.4 反复阅读,并反复修正2.1-2.3所做的事。
2.5 坚持:开始阶段读源码会非常难受,不停的跳转好像进入了迷宫,这时只有坚持才能解决。
Springframework认识总结
1、Springframework发展到6.0.8,系统复杂性很高,从类个数可见一般:
Beans: 313个类
Context: 517个类
Core: 634个类
SpEL: 110个类
AOP: 203个类
2、Spring提供了依赖导致能力,其框架本身也是坚持依赖导致:接口先行。其具体好处如下:
2.1 接口先行,是框架提供扩展能力的基础机制。扩展不可使应用介入或使用展框能力,同时支持扩展框架本身。
2.2 标记接口使用:标记接口指接口没有任何方法,仅代表某类抽象程度很高的事情。如Aware接口就是典型标记接口,代表应用可以感知(获取)应用某一个方法的能力(如ApplicationContextAware、EnvironmentAware、ResourceLoaderAware、MessageSourceAware…)
2.3 接口解决多继承问题:如应用容器(ApplicationContext)作为应用运行的环境,需要包括很多不同的东西,通过接口就可以统一起来,见下图:
3、类继承层次深:层次5个以上是常见的,超过9个(含接口)也不罕见。这样的优点是非常符合OOD原则,易于修改和扩展;缺点是程序复杂性大大提高。常见阅读障碍是:继承层次中间某一个方法的实现是抽象的或空方法体,具体实现在子孙类中,这时需要手工去找这个实现方法体。例图如下:
4、Spring提供的扩展机制,框架本身也是用这个进行扩展。如Bean实例化和初始化过程有很多扩展点,不仅应用可利用这些扩展点利用框架能力,而且框架本身就是这样使用的,如解析BeanDefinition实现中,标准命名空间(bean)解析是默认的,非标准命名空间(如context、aop等)是定制入口,不同元素入口对应不同的解析实现,例如context:annotation-config和context:component-scan对应不同的实现,前者对应解析器AnnotationConfigBeanDefinitionParser,后者对应解析器ComponentScanBeanDefinitionParser。这样优点当然是非常优雅的实现了扩展机制,难点程序可读性下降很多,阅读者如果不通过跟踪调试方式,甚至找不到正确的解析器。例图如下:
学习收获
通过系统阅读框架源码,提升了如下方面的能力:
1、解决应用问题能力:随着对框架认识加深,提高了对基于框架的应用问题的解决能力。
2、提升设计能力:学习框架实现,探究背后的设计原因,可提升自己对应用系统设计和重构能力。
3、学习优秀的编码风格:基本上所有的类、属性、方法均有注释,其中接口注释更详细。所有注释均符合JavaDoc规范。
4、学习优秀的框架,可以扩大阅读者技术眼界,直观体验业界大牛是如何解决问题的。
至此,本次学习就算结束了。虽然这次学习基本搞懂了Springframework是如何实现的,但由于个人精力有限,加之框架的复杂性,导致泛泛阅读的源码大约只有一半,精读可能只有四分之一;对于源码理解的正确性、准确性也不能保证100%,不得不说这是不小的遗憾。