likes
comments
collection
share

Spring Framework海报

作者站长头像
站长
· 阅读数 56

友情提示,图在最底部。

标题所指的海报是指类似CheatSheet的可打印手册,比如极客时间出的的知识地图知识手册

  1. 便于理解。一图胜千言,有了全局的知识地图,就可以从整体上把握,避免迷失在细节中。对于Spring框架这种庞大的设计显然更是如此;
  2. 转换角度。小册是从源码解析的角度来分析Spring。但是普通开发者通常接触不到Spring的底层细节,反而更关心如何使用。因此,我们最需要掌握的是Spring框架提供的扩展点,以及这些扩展点在整个执行流程中的位置。所以,一个好的全局图应该跳脱源码,体现运行期的逻辑流。 上面的ASP.NET海报就是典型;
  3. 易于记忆。陈皓分享过“知识压缩”的概念。一门知识如果细节太多,是不可能记得住的。把知识学会之后做个压缩,提取核心精华,就可以长久地保存在大脑里。具体的细节在使用时再查阅资料即可。

另外,由于Spring的范围太大了,因而不可能放到一张图里去。类似 ASP.Net Web Api 的海报应该对应的是Spring MVC。

网上搜集篇

首先我在网上搜罗了一圈,发现国外很少有人研究Spring内幕。看来还是国内比较卷~

全局图

下面这个图接近一幅完整的海报,但是偏介绍,帮助不大。 Spring Framework海报

时序图

这篇文章总结的比较好。缺点是类和步骤太多,记不住。

下面是一些补充。

生命周期&扩展点

下面的几个图聚焦于Bean的生命周期:

这个图区分了生命周期的阶段,但内容不足。 Spring Framework海报

这个图区分了类和方法的颜色,不过缺少注释。 Spring Framework海报

这个图则对相同的类采用了同样的颜色。 Spring Framework海报

这几个图的缺点是类似的:偏文字化,不符合开篇提到的几点要求。既然没有满意的,那就自己来吧。

闭门造车篇

首先,我们先用文字整理一下的Bean生命周期,关注逻辑流程和扩展点。

Bean的生命周期可以分为以下几个阶段,其中初始化阶段被细分为了实例化和初始化。

  • 创建BeanDefinition阶段
  • Bean的实例化
  • Bean的初始化
  • 运行期
  • Bean的销毁

创建BeanDefinition

  • 对于XML配置,就是在refresh()的第2步obtainFreshBeanFactory()中,最终调用XmlBeanDefinitionReader读取配置,注册BeanDefinition.
  • 对于注解配置,就是在refresh()的第5步invokeBeanFactoryPostProcessors()中,最先调用了ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry方法,该方法会扫描注解。
  • 当然,可以定义其它的BeanFactoryPostProcessor,以对创建出来的BeanDefinition做修改。扩展点1

Bean的实例化(就是new出对象)

  • 入口是refresh()的第11步,finishBeanFactoryInitialization().
  • 最终会调用到AbstractBeanFactory的getBean()和doGetBean()方法
  • 先会做循环依赖的处理
  • 接着调用AbstractAutowireCapableBeanFactory#createBean()
  • 先给InstantiationAwareBeanPostProcessor一个机会,直接拦截实例化过程 扩展点2
  • 否则进入doCreateBean(),先调用createBeanInstance() 创建实例
  • 如果BD指定了supplier 或factoryMethod,则直接调用
  • 否则,找到合适的constructor并使用它创建实例。创建实例可以使用java反射,或cglib. 如果有参数则先搞定参数。此处有个SmartInstantiationAwareBeanPostProcessor的扩展,可以指定使用哪个constructor。扩展点3

Bean的初始化

  • doCreateBean继续,先收集Bean的注解信息,如有必要就提早暴露Bean,以解决循环依赖
  • 调用populateBean()进行属性赋值+依赖注入:
    • 先回调InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法,在设置属性之前调用 扩展点4
    • (根据name或type)自动注入属性,得到一个PropertyValues对象,再回调InstantiationAwareBeanPostProcessor的postProcessPropertyValues()和postProcessPropertyValues()方法,可以再修改属性数据。 扩展点5 这里有个重要的实现类AutowiredAnnotationBeanPostProcessor,它会做自动注入,通过反射的方式设置bean的字段
    • 接着调用applyPropertyValues(),把pvs应用到Bean对象上。最终也是通过反射。
  • 接着调用initializeBean(),进行初始化。这里面一共有4步
    • 调用Aware接口(比如BeanNameAware)
    • 调用各种BeanPostProcessor的postProcessBeforeInitialization()。其中某些BeanPostProcessor会调用@PostConstruct标注的方法 扩展点6
    • 调用InitializingBean接口的afterPropertiesSet()方法和自定义的init-method 扩展点7
    • 回调各种BeanPostProcessor的applyBeanPostProcessorsAfterInitialization() 方法。AOP就是在这里实现的。扩展点8
  • 最后一步,是注册DisposableBean
  • 最后,在应用启动时,会调用所有实现了Lifecycle的start()方法 扩展点9

Bean的销毁

  • 先是容器的stop,调用所有Lifecycle的stop(),对应之前的start() 扩展点10
  • 接着是容器的close(),重要的方法是destroyBeans(),销毁所有的bean。其中会调用@Predestroy、 DisposableBean的destroy()方法、destroy-method方法。扩展点11
  • 最后丢弃BeanFactory。

做完这一步,我们至少已经把知识结构化了。接下来就是对着文字画图。

图来了

Spring Framework海报

可以打印出来随手参照。

总结

有了最核心的Bean生命周期全景图,Spring的其它工作过程都可以对照着看了。后续如有必要,我会补充一些其它模块的海报。欢迎拍砖。

转载自:https://juejin.cn/post/6956814839729618957
评论
请登录