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 ...
随机推荐
- Python_string.Template的使用
Template是python string提供的一个字符串模板功能.主要用于文本处理 from string import Template s = Template('$who 在 $do') t ...
- 华为云 Kubernetes 管理员实训 三 课后作业
Exercise 1 通过Deployment方式,使用redis镜像创建一个pod.通过kubectl获得redis启动日志. Deployment的名称为<hwcka-003-1-你的华为云 ...
- spring cloud --- Zuul --- 心得
spring boot 1.5.9.RELEASE spring cloud Dalston.SR1 1.前言 什么是 Zuul? Zuul是微服务网关,与Gateway类似 ,根据请 ...
- linux获取 GPG 密钥失败
实质性问题就是自己系统没有yum的GPG密钥 查看自己系统版本 cat /etc/issue 登陆mirrors.163.com 找到自己系统对应的密钥 RPM-GPG-KEY-CentOS-3 ...
- vue3.0+ts+setup语法糖props写法
写法一 import defaultImg from '@/assets/images/defaultImg.png' const props = defineProps({ src: { type: ...
- 【Java】流程控制
文章目录 流程控制 一.用户交互scanner 1.1 Scanner对象 1.2 Scanner进阶使用 二.顺序结构 三.选择结构 3.1 if单选择结构 3.2 if双选择结构 3.3 if多选 ...
- Sentry 开发者贡献指南 - 数据库迁移
Django 迁移是我们处理 Sentry 中数据库更改的方式. Django 迁移官方文档:https://docs.djangoproject.com/en/2.2/topics/migratio ...
- Python 根据id生成唯一码
Python 根据id生成唯一码 最近业务中遇到需要分享某个文案,复制文案打开APP需要提取文案中包含的id,但又不想明文暴露id,所以需要对id进行加密,很想让前端来做,可惜多个前端协调起来不方便( ...
- 508. Most Frequent Subtree Sum
Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a ...
- java内部类概述和修饰符
1 package face_09; 2 /* 3 * 内部类访问特点: 4 * 1,内部类可以直接访问外部类的成员. 5 * 2,外部类要访问内部类,必须建立内部类的对象. 6 * 7 * 一把用于 ...