基本概念梳理

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,来看一下它的源码:

查看代码

  1. package org.springframework.beans.factory;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.core.ResolvableType;
  4. import org.springframework.lang.Nullable;
  5. public interface BeanFactory {
  6. //对FactoryBean的转义定义,因为如果使用Bean名字来进行搜索FactoryBean的话得到的只是工厂生成的对象
  7. //如果需要得到工厂本身,需要转义
  8. String FACTORY_BEAN_PREFIX = "&";
  9. //根据Bean的名字获得在IoC容器种的Bean的实例
  10. Object getBean(String name) throws BeansException;
  11. //根据Bean的名字和Class类型来得到Bean的实例,同时增加了类型安全验证机制
  12. <T> T getBean(String name, Class<T> requiredType) throws BeansException;
  13. Object getBean(String name, Object... args) throws BeansException;
  14. <T> T getBean(Class<T> requiredType) throws BeansException;
  15. <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
  16. <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
  17. <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
  18. //提供对Bean的检索,看下具备Bean的名字的Bean是否存在于IoC容器中
  19. boolean containsBean(String name);
  20. //判断具备name的Bean是否存在于容器,并且是否是单例
  21. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
  22. //判断具备name的Bean是否存在于容器,并且是否是原型
  23. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
  24. boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
  25. boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
  26. //得到Bean实例的Class类型
  27. @Nullable
  28. Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  29. @Nullable
  30. Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
  31. //得到Bean实例在IoC容器中的别名,当然你输入别名来搜索,结果原名也会包含其中
  32. String[] getAliases(String name);
  33. }

从上面可以看出,在BeanFactory里只对IoC容器的基本行为做了定义,根本不关心你的Bean是如何定义及怎样加载的。正如我们只关心能从工厂里得到什么产品,不关心工厂是怎么生产这些产品的。要知道工厂是如何产生对象的,我们需要看具体的IoC容器实现,Spring里面提供了许多IoC容器实现,比如GenericApplicationContext、ClasspathXmlApplicationContext等。

PS:ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能,还为用户提供了以下附加服务。

  1. 支持信息源,可以实现国际化(实现MessageSource接口)。
  2. 访问资源(实现ResourcePatternResolver接口,后面系列会讲到)。
  3. 支持应用事件(实现ApplicationEventPublisher接口)。

2、BeanDifinition

Spring IoC容器管理我们定义的各种Bean对象及其相互关系,Bean对象在Spring实现中是以BeanDefinition来描述的,其继承体系如下图所
示。

3、BeanDefinitionReader

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

总结

通过前面的分析,我们对Spring框架体系有了一个基本的宏观了解,希望可以好好理解,最好在脑海中形成画面,为后面的学习
打下良好的基础。

Spring5源码解析系列一——IoC容器核心类图的更多相关文章

  1. Spring源码解析三:IOC容器的依赖注入

    一般情况下,依赖注入的过程是发生在用户第一次向容器索要Bean是触发的,而触发依赖注入的地方就是BeanFactory的getBean方法. 这里以DefaultListableBeanFactory ...

  2. Spring源码解析一:IOC容器设计

    一.IOC接口设计 IOC容器设计的源码主要在spring-beans.jar.spring-context.jar这两个包中.IOC容器主要接口设计如下: 这里的接口设计有两条主线:BeanFact ...

  3. Spring源码解析二:IOC容器初始化过程详解

    IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...

  4. Spring源码分析(三)容器核心类

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在上一篇文章中,我们熟悉了容器的基本用法.在这一篇,我们开始分析Spri ...

  5. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  6. Spring5源码解析-Spring框架中的单例和原型bean

    Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...

  7. Spring5源码解析-论Spring DispatcherServlet的生命周期

    Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...

  8. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

随机推荐

  1. Python_string.Template的使用

    Template是python string提供的一个字符串模板功能.主要用于文本处理 from string import Template s = Template('$who 在 $do') t ...

  2. 华为云 Kubernetes 管理员实训 三 课后作业

    Exercise 1 通过Deployment方式,使用redis镜像创建一个pod.通过kubectl获得redis启动日志. Deployment的名称为<hwcka-003-1-你的华为云 ...

  3. spring cloud --- Zuul --- 心得

    spring boot      1.5.9.RELEASE spring cloud    Dalston.SR1 1.前言 什么是 Zuul? Zuul是微服务网关,与Gateway类似 ,根据请 ...

  4. linux获取 GPG 密钥失败

    实质性问题就是自己系统没有yum的GPG密钥 查看自己系统版本 cat /etc/issue 登陆mirrors.163.com 找到自己系统对应的密钥  RPM-GPG-KEY-CentOS-3   ...

  5. vue3.0+ts+setup语法糖props写法

    写法一 import defaultImg from '@/assets/images/defaultImg.png' const props = defineProps({ src: { type: ...

  6. 【Java】流程控制

    文章目录 流程控制 一.用户交互scanner 1.1 Scanner对象 1.2 Scanner进阶使用 二.顺序结构 三.选择结构 3.1 if单选择结构 3.2 if双选择结构 3.3 if多选 ...

  7. Sentry 开发者贡献指南 - 数据库迁移

    Django 迁移是我们处理 Sentry 中数据库更改的方式. Django 迁移官方文档:https://docs.djangoproject.com/en/2.2/topics/migratio ...

  8. Python 根据id生成唯一码

    Python 根据id生成唯一码 最近业务中遇到需要分享某个文案,复制文案打开APP需要提取文案中包含的id,但又不想明文暴露id,所以需要对id进行加密,很想让前端来做,可惜多个前端协调起来不方便( ...

  9. 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 ...

  10. java内部类概述和修饰符

    1 package face_09; 2 /* 3 * 内部类访问特点: 4 * 1,内部类可以直接访问外部类的成员. 5 * 2,外部类要访问内部类,必须建立内部类的对象. 6 * 7 * 一把用于 ...