Spring5源码解析系列一——IoC容器核心类图
基本概念梳理
IoC(Inversion of Control,控制反转)就是把原来代码里需要实现的对象创建、依赖,反转给容器来帮忙实现。我们需要创建一个容器,同时需要一种描述来让容器知道要创建的对象与对象的关系。这个描述最具体的表现就是我们所看到的配置文件。
DI(Dependency Injection,依赖注入)就是指对象被动接受依赖类而不自己主动去找,换句话说,就是指对象不是从容器中查找它依赖的类,而是在容器实例化对象时主动将它依赖的类注入给它。
撇开Spring源码不看,从我们自身的理解出发,如果我们来开发这样的容器,需要考虑下面几个问题:
- 对象与对象的关系怎么表示?
答案:可以用XML、Properties等语义化的配置文件来表示。
- 描述对象关系的文件存放在哪里?
答案:可以是Classpath、FileSystem、URL网络资源或者servletContext等。
- 不同的配置文件对对象的描述不一样,如标准的、自定义声明式的,如何统一?
答案:这就可能在内部需要有一个统一的关于对象的定义,所有外部的描述都必须转化成统一的描述定义。
- 如何对不同的配置文件进行解析?
答案:需要对不同的配置文件语法采用不同的解析器。
Spring核心容器类图
1、BeanFactory
Spring中Bean的创建是典型的工厂模式,这一系列的Bean工厂,即IoC容器,为开发者管理对象之间的依赖关系提供了很多便利和基础服务,在Spring中有许多IoC容器的实现供用户选择,其相互关系如下图所示。

其中,BeanFactory作为最顶层的一个接口类,定义了IoC容器的基本功能范围,BeanFactory有三个重要的子类:ListableBeanFactory、
HierarchicalBeanFactory和AutowireCapableBeanFactory。但是从类图中我们可以发现最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。那么为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有它的使用场合,主要是为了区分在Spring内部操作过程中对象的传递和转化,对对象的数据访问所做的限制。
例如,ListableBeanFactory接口表示这些Bean可列表化,而HierarchicalBeanFactory表示这些Bean 是有继承关系的,也就是每个Bean 可能有父 Bean。AutowireCapableBeanFactory 接口定义Bean的自动装配规则。这三个接口共同定义了Bean的集合、Bean之间的关系及Bean行为。最基本的IoC容器接口是BeanFactory,来看一下它的源码:
查看代码
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
public interface BeanFactory {
//对FactoryBean的转义定义,因为如果使用Bean名字来进行搜索FactoryBean的话得到的只是工厂生成的对象
//如果需要得到工厂本身,需要转义
String FACTORY_BEAN_PREFIX = "&";
//根据Bean的名字获得在IoC容器种的Bean的实例
Object getBean(String name) throws BeansException;
//根据Bean的名字和Class类型来得到Bean的实例,同时增加了类型安全验证机制
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
//提供对Bean的检索,看下具备Bean的名字的Bean是否存在于IoC容器中
boolean containsBean(String name);
//判断具备name的Bean是否存在于容器,并且是否是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//判断具备name的Bean是否存在于容器,并且是否是原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
//得到Bean实例的Class类型
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
//得到Bean实例在IoC容器中的别名,当然你输入别名来搜索,结果原名也会包含其中
String[] getAliases(String name);
}
从上面可以看出,在BeanFactory里只对IoC容器的基本行为做了定义,根本不关心你的Bean是如何定义及怎样加载的。正如我们只关心能从工厂里得到什么产品,不关心工厂是怎么生产这些产品的。要知道工厂是如何产生对象的,我们需要看具体的IoC容器实现,Spring里面提供了许多IoC容器实现,比如GenericApplicationContext、ClasspathXmlApplicationContext等。
PS:ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能,还为用户提供了以下附加服务。
- 支持信息源,可以实现国际化(实现MessageSource接口)。
- 访问资源(实现ResourcePatternResolver接口,后面系列会讲到)。
- 支持应用事件(实现ApplicationEventPublisher接口)。
2、BeanDifinition
Spring IoC容器管理我们定义的各种Bean对象及其相互关系,Bean对象在Spring实现中是以BeanDefinition来描述的,其继承体系如下图所
示。

3、BeanDefinitionReader
Bean的解析过程非常复杂,功能被分得很细,因为这里需要被扩展的地方很多,必须保证足够的灵活性,以应对可能的变化。Bean的解析
主要就是对Spring配置文件的解析。这个解析过程主要通过BeanDefinitionReader来完成,看看Spring中BeanDefinitionReader的类结构图,如下图所示。

总结
通过前面的分析,我们对Spring框架体系有了一个基本的宏观了解,希望可以好好理解,最好在脑海中形成画面,为后面的学习
打下良好的基础。
Spring5源码解析系列一——IoC容器核心类图的更多相关文章
- Spring源码解析三:IOC容器的依赖注入
一般情况下,依赖注入的过程是发生在用户第一次向容器索要Bean是触发的,而触发依赖注入的地方就是BeanFactory的getBean方法. 这里以DefaultListableBeanFactory ...
- Spring源码解析一:IOC容器设计
一.IOC接口设计 IOC容器设计的源码主要在spring-beans.jar.spring-context.jar这两个包中.IOC容器主要接口设计如下: 这里的接口设计有两条主线:BeanFact ...
- Spring源码解析二:IOC容器初始化过程详解
IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...
- Spring源码分析(三)容器核心类
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在上一篇文章中,我们熟悉了容器的基本用法.在这一篇,我们开始分析Spri ...
- Spring源码解析系列汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...
- Spring5源码解析-Spring框架中的单例和原型bean
Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...
- Spring5源码解析-论Spring DispatcherServlet的生命周期
Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
随机推荐
- spring-data-jpa ----OneToMany 一对多
环境搭建 导入依赖 maven3.6.3 <properties> <spring.version>5.2.5.RELEASE</spring.version> ...
- 2021最新Termux安装Metasploit
前言 因为某些脚本小子的用Termux搞破坏,所以Termux软件源移除了对Metasploit的支持,所以就不能直接用pkg和apt直接安装了. 但是不用担心,noob-hacker大大写了一个工具 ...
- preg_match绕过总结
preg_match绕过总结 什么是preg_match 绕过方法 1.数组绕过 preg_match只能处理字符串,当传入的subject是数组时会返回false 2.PCRE回溯次数限制 PHP利 ...
- winform控件拖动
示例代码 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Form ...
- 【笔记】macos上部署thanos_receiver + thanos_query
为了方便起见,在mac笔记本上进行了测试 1.写一个发送数据的客户端 package main import ( "fmt" "io/ioutil" " ...
- Spring 官宣发布 Spring Boot 3.0 第一个里程碑 M1,从 Java 8 提升到 Java 17!
Spring官方于2022年1月20日发布Spring Boot 3.0.0-M1版本,预示开启了Spring Boot 3.0的里程碑,相信这是通往下一代Spring框架的激动人心的旅程. 接下来一 ...
- 外观模式(Facade模式)
外观模式的定义与特点 外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式.该模式对外有一个统一接口,外部应用程序不用关心内部子系 ...
- C++构造函数语义学(一)(基于C++对象模型)
如果一个类没有自己的构造函数,编译器会在需要的时候为其合成一个出来,俗称:合成默认构造函数.但是请注意是在需要的时候,并不是所有情况. 请看下面代码: 1 #include<iostream&g ...
- mac 更新到big sur 后,parallels虚拟机的一些问题:由于您尚未获得访问其中一些文件的授权,所以您不能恢复“Windows 10
由于您尚未获得访问其中一些文件的授权,所以您不能恢复"Windows 10 Mac上使用PD虚拟机,打开系统时提示"由于您尚未获得访问其中一些文件的授权,所以您不能恢复" ...
- DB2重组表失败处理办法
set integrity for XXX all immediate unchecked reorg table XXX allow no access 如set integrity for a a ...