从Spring中学到的【1】–读懂继承链

最近看了一些 Spring 源码,发现源码分析的文章很多,而底层思想分析的文章比较少,这个系列文章准备总结一下Spring中给我的启示,包括设计模式思想、SOLID设计原则等,涉及一些编程的基本原则,虽然看似简单,实则”小道理、大学问”。
我尽量遇到的问题谈起,再说解决方案,同时至少举两个例子。
这些方法都是基于我遇到的一些实际代码,掌握了基本思想,就可以举一反三。

让人头晕眼花的跳转

如果你通过某些培训机构的源码课,就会发现他们的老师在讲源码的时候在类之间、方法之间不停地跳,学员一脸懵逼。因为如果不理解老师讲课的思路,或者是稍微走一下神,就会觉得自己跟不上了。

其实,问题就在于需要理解源码的基本流程和继承链的这种单一职责原则。

读懂继承链

面向对象的特点是封装继承和多态,封装体现在私有方法。

在Spring中,常见的模式是顶层为接口,然后是抽象类,最后是各个实现类。

接口负责对外暴露,符合面向接口编程的准则,在更改实现类时,可以减小对于代码的改动,保证了代码依赖于抽象(接口)。.

抽象类一般使用模板模式,实现了逻辑的组装,把子类中的公用逻辑抽取出来,方便子类编写;模板方法一般为固定的执行链,我们读源码时,可以予以关注。比如常见的AbstractApplicationContext::refresh 方法,AbstractBeanFactory::doGetBean方法。由于接口一般只能暴露方法声明,抽象类可以实现一些状态的getter,settter,这样子类访问这些状态数据只需要调用方法即可。

实现类通常有多个,比如todo。有些时候当实现类只有一个或者有一个默认实现类时,常常使用default命名,比如 DefaultListableBeanFactory. 读源码时可以选择地阅读默认实现。

Java 只支持单继承,这种语言层面的规范方便了我们阅读源码,一个方法的实现必然在一条继承链中。

举例1:

从Spring中学到的【1】--读懂继承链

Spring中BeanFactory的默认实现是 DefaultListableBeanFactory, 通过继承图可以看出,有多个抽象类,从上到下分别实现了以下的能力:

  • 别名注册( SimpleAliasRegistry
  • 单例注册( DefaultSingletonBeanRegistry
  • FactoryBean 注册( FactoryBeanRegistrySupport
  • bean工厂接口(主要就是getBean相关的一些方法)( AbstractBeanFactory
  • 自动装配( AbstractAutowireCapableBeanFactory

同时我们还可以看到,基本上每一个抽象类都对应一个实现的接口:

AliasRegistrySimpleAliasRegistry

SingletonBeanRegistryDefaultSingletonBeanRegistry

AbstractBeanFactoryConfigurableBeanFactory

AbstractAutowireCapableBeanFactoryAutowireCapableBeanFactory

注意到 DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory,这个接口实现了一些简化配置 beanFactory 的方法,是一个常用的基础设施类(接口)。

实际上,这个设计也是不得已而为之。Java只支持单继承,理想的情况下, DefaultListableBeanFactory 需要继承不同的trait,即单例注册、FactoryBean注册等功能模块,Configurable, Listable, **Capable恰好是这种设计思想的体现。如果最终的DefaultListableBeanFactory写成一个类,一定是巨大的,但是假如我们将BeanFactory不同的特性做拆分的话,就会得到如图所示的看似复杂的接口继承关系。

这种松散的接口继承关系正是我们需要的,举例来说,autowireCapable 和 hierarchical并没有实际上的联系,一个关注属性注入,另一个则关注bean工厂的层级关系(可以有父工厂)。

假设每一个松散的接口都有几个或多个实现,不管其是否是抽象类或者具体实现,我们只有通过多继承或者委托模式组装得到 DefaultListableBeanFactory

这就是矛盾的地方,单一的继承链和松散的接口,其结果就是抽象类具有了一些不必要的功能。比如 AbstractAutowireCapableBeanFactory 具有了Configurable、aliasRegistry等能力。这种情况是我们阅读源码是需要注意的。

Spring通过将单继承链分解为6个类,将 DefaultListableBeanFactory 进行了功能拆分,符合开闭原则,每个类也符合单一职责原则的要求。

通过以上分析,打开 DefaultListableBeanFactory 的源码,虽然有2000多行,我们可以清楚地看出类的结构,包括1. 继承链相关:不同抽象方法的实现、未在抽象类中实现的接口方法的实现。2. BeanDefinitionRegistry 3. ConfigurableListableBeanFactory 4. Serializable

举例2:

从Spring中学到的【1】--读懂继承链

类似如上的分析,AnnotationConfigApplicationContext 的继承链如下:

DefaultResourceLoader → AbstractApplicationContext → GenericApplicationContext → AnnotationConfigApplicationContext

每个类实现的功能即其直接实现的接口,有些类通过类名也可以快速得知其实现的功能。不再赘述。

GenericApplicationContext 实现了BeanDefinitionRegistry,直接委托BeanFactory的实现给DefaultListableBeanFactory,子类包括AnnotationConfigApplicationContext 和mvc容器等。

在抽象类AbstractApplicationContext可以看到大家耳熟能详的refresh方法。

ApplicationContext更是重量级,作为应用容器,拥有BeanFactory外的事件广播、国际化、资源读取等能力。

由于ApplicatoinContext是大接口,是不同功能的最终整合,所以我们看到的接口继承关系并不复杂。

举例3:

从Spring中学到的【1】--读懂继承链

我们知道MVC模型中具有中央调度器,在SpringMvc中体现为DispatcherServlet,其继承链如图。

了解过servlet的人都知道HttpServlet具有doGet、doPost等方法,子类重新后所有方法都转发到DispatcherServlet中,doService→doDispatch执行了我们熟知的分发模板逻辑:简单来说就是

getHandlergetHandlerAdapterapplyPreHandle**handle**applyPostHandleprocessDispatchResult

processDispatchResult中包含异常处理,render和afterCompletion

我们随便选择一个方法,比如初始化mvc容器,其必在继承链上的某个类中进行实现,通过分析源码可以看出: initWebApplicationContext在FrameworkServlet中实现。
GenericServlet暴露init方法。
HttpServletBean实现了init方法,在init方法中暴露 initServletBean方法。
FrameworkServlet实现 initServletBean方法,其中实现了 initWebApplicationContext方法。

虽然执行初始化mvc容器方法需要在继承链上来回跳转,但是其实现了单一职责原则,每一个类负责实现了特定的功能,模板类实现了模板流程,实现类实现具体实现。

Original: https://www.cnblogs.com/dahua-dijkstra/p/16691232.html
Author: 大华dijkstra
Title: 从Spring中学到的【1】–读懂继承链

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714511/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • idea 内存溢出

    重启idea posted @2020-10-13 15:30 哈哈呵h 阅读(858 ) 评论() 编辑 Original: https://www.cnblogs.com/ya…

    技术杂谈 2023年5月30日
    0111
  • 保姆教程系列二、Nacos实现注册中心

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 上篇我们介绍到 保姆教程系列一、Linux搭建Nacos 注册中心原理 一、环境准备 Java版本:1.8+ (L…

    技术杂谈 2023年7月11日
    093
  • Vue-cli介绍

    vue基本语法非常容易理解,如果在接触vue之前,接触过微信小程序,基本可以说轻车熟路.反过来也是如此. vue 之所以强大切易用离不开vue-cli\vue-router\vue…

    技术杂谈 2023年7月11日
    065
  • python中的反射

    python反射简介 所谓反射是指通过字符串的方式获取对象,然后执行对象的属性或方法。在python中一切皆对象,因此我们可以对一切事物进行发射。 关于反射python为我们提供了…

    技术杂谈 2023年7月11日
    084
  • Java中流水编号的生成

    在开发中,遇到这样一个需求,在介质资料新增时,需要生成一个介质编号,格式为”JZ+yyyyMMdd+4位递增数字”先是使用百度找寻解决方法。解决方法 里面的…

    技术杂谈 2023年7月24日
    085
  • 【转】SDN技术原理介绍

    原文:https://cloud.tencent.com/developer/news/211547 Original: https://www.cnblogs.com/oxspi…

    技术杂谈 2023年5月30日
    091
  • Swift开发iOS应用过程中的问题和解决记录

    虚拟机里安装OSX+XCode开发环境 用真机的请直接跳过这个部分。 主要是在VitrualBox里安装mac系统和xcode,参考这篇教程,VirtualBox的版本是4.3.1…

    技术杂谈 2023年5月31日
    0126
  • 《Generative Adversarial Networks for Hyperspectral Image Classification 》论文笔记

    GAN是一种新的模型,通常包含生成模型G和判别模型D。模型G和D以对抗性的方式进行训练,其中G试图生成尽可能真实的假输入,D试图对真实输入和假输入进行分类。在这个对抗性博弈中,双方…

    技术杂谈 2023年6月21日
    098
  • 燕千云YQCloud数智化业务服务平台发布1.12版本

    2022年4月29日,燕千云 YQCloud 数智化业务服务平台发布1.12版本,优化客户服务场景、深化智能预测服务的应用,加强系统在多渠道方面的集成,全面提升企业数智化服务的能力…

    技术杂谈 2023年7月23日
    097
  • 微服务中的CAP定律

    说到微服务,先给大家提一下CAP分布式应用知识吧,无论你微服务使用的是阿里云开源的Dubbo还是基于Springboot的一整套实现微服务的Springcloud都必须遵循CAP定…

    技术杂谈 2023年6月1日
    088
  • PHP——JWT与Token区别

    TOKEN 概念: 令牌,就是加密的字符串, 是访问资源的凭证。Token需要查库验证token 是否有效。 JWT JWT是json web token缩写。它将用户信息加密到t…

    技术杂谈 2023年5月31日
    0102
  • 主机回来以及,简单的环境配置(RTX3070+CUDA11.1+CUDNN+TensorRT)

    紧接着前几天的事: 特殊的日子,想起了当年的双(1080TI)显卡装机实录 和 炼丹炉买不起了:聊一聊这段日子的显卡行情 之后,决定买一台整机玩玩。 而现在,主机终于回!来!了!主…

    技术杂谈 2023年7月11日
    0128
  • 深入汇编指令理解Java关键字volatile

    volatile是什么 volatile关键字是Java提供的一种轻量级同步机制。它能够保证可见性和有序性,但是不能保证原子性 可见性 对于volatile的可见性,先看看这段代码…

    技术杂谈 2023年7月25日
    086
  • JSON和JS对象之间的互转

    1. jQuery插件支持的转换方式 $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成json对象…

    技术杂谈 2023年5月30日
    086
  • 【邂逅Django】——(二)数据库配置

    🔥 邂逅Django – 目录 ✅ Part 1:【邂逅Django】—— (一)创建项目 ✅ Part 2:【邂逅Django】—— (二)数据库配置 🛠️ Part…

    技术杂谈 2023年7月24日
    092
  • 五、JDK的安装与配置

    一、JDK下载与安装 1.1、下载JDK安装包 博主在这里给大家准备了一个64位操作系统的jdk1.8以便大家下载(使用的是迅雷)点击此处下载提取码:dfbt 如果其他小伙伴的电脑…

    技术杂谈 2023年6月21日
    076
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球