专栏首页星月小站Spring框架源码脉络分析(一):IoC与容器、Bean和BeanDefinition

Spring框架源码脉络分析(一):IoC与容器、Bean和BeanDefinition

系列文章概述

  • 系列文章主页:Spring框架源码脉络分析总结
  • 阅读建议:读者至少要使用过Spring框架,了解Spring的配置方法,包括Xml文件配置和注解配置。
  • 分析的源码版本:spring-framework : 5.2.0.RELEASE
  • 官方参考文档:Spring Framework Documentation
  • 本文主要以分析Spring源码模块脉络为主,主要带领读者理清Spring运行的流程和脉络,不会深究一些知识细节,避免陷入细节无法自拔,所以仅贴出来核心的源码进行分析备注,对于每个步骤的细节,需要读者自行深入了解

IoC与容器

IoC:即控制反转机制。在Spring中的实现表现为IoC容器,属于Spring Core模块最核心的部分。

IoC其实是一种设计思想,其本质就是将对象的创建、依赖关系的管理以及生命周期的的控制交由IoC容器,或者说是框架来管理,解放了码农的双手。

IoC的存在离不开另外一个设计思想——依赖注入(DI)。

  1. 依赖注入最直观的解释就是一个实例化对象只接受一个参数——已经实例化的对象。也就是说一个对象A中如果依赖另一个对象B,必须直接注入一个已经实例化的对象B,对象A本身不关注对象B如何实例化的,这样就将对象间的依赖尽可能的解耦。
  2. 而控制对象实例化和操作对象注入的【控制】权限就交给了第三方——spring框架,进行控制反转,这就是IoC。
  3. 既然有了这种设计思想,那么对象B是如何注入对象A中去的呢?其实很简单,就是通过四种常用的注入方式:Set注入、接口注入、注解注入和构造器注入。
  4. 所以IoC、依赖反转和IoC容器的关系可以看做下图:

IoC在spring中依托于一个类似工厂的IoC容器,将所有的bean都托管在容器中,随时供框架进行调用,spring的容器可以让码农避免在各处使用new来创建类,并且做到了统一维护,码农在创建实例的时候不需要了解其中的细节。

什么是容器:Spring官方文档中对容器的描述如下:

The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.

意思是org.springframework.context.ApplicationContext这个接口就代表了Spring的容器,这个容器负责实例化、配置以及装配一个Bean。

所以简单的从代码上看,我们可以认为容器就是一个ApplicationContext的实现类的实例化对象。当我们使用Spring框架对对象进行管理时,Spring框架会自动为我们创建一个容器用来管理对象,这个容器是Spring框架的核心。我们将在第二章节中重点来分析Spring中的容器类。

Bean和BeanDefinition

在Spring中,Bean是一等公民,我们常说的对象在Spring中就描述为Bean。Bean的本质其实就是Java对象,是我们期望从Spring容器中获取到的实例。

而如果我们去阅读Spring的源码,会发现在Spring中大量操作的是一种名为BeanDefinition的类,而不是Bean。在Spring中,BeanDefinition是对Bean的定义与描述,Bean和BeanDefinition的关系有点像装饰器模式的增强:

  • Spring容器在运行过程中需要对Bean,也就是我们的Java对象进行操作与管理,其中需要进行一些额外的操作,而这些操作在Bean中是没有办法体现的。所以Spring提供了一种无侵入式的方法,对Bean进行包装,将各种描述信息和控制方式信息包装进BeanDefinition中,也就是说BeanDefinition中既有Bean对象的信息,又有描述和控制信息。
  • 那么这些额外的信息是什么呢:其实就是我们经常在xml或者注解文件中使用的配置属性,比如scope属性用来控制Bean是单例还是多例,lazy-init属性用来控制Bean实例是否延迟加载,primary设置为true的Bean将会是类的优先实现类等等。这些额外的信息和参数,就将随着Bean对象一起被封装进BeanDefinition中,以便于Spring根据用户传入的需求对Bean进行管理。

Spring中BeanDefinition的接口体系如下图:

其中各接口与类的作用如下:

  • BeanMetadataElement接口: BeanDefinition元数据,定义了返回该Bean的来源的抽象接口。
  • AttributeAccessor接口: 定义了对元数据访问的抽象接口。
  • AttributeAccessorSupport抽象类: AttributeAccessorSupport是实现了AttributeAccessor的抽象类,实现了一些基础通用方法,内部由LinkedHashMap实现。
  • BeanDefinition接口: BeanDefinition体系的顶级基础接口,定义了存储描述Bean的元数据的各种变量与方法,包括Bean的类名、scope属性、是否懒加载等一系列属性。
  • AbstractBeanDefinition抽象类: BeanDefinition接口的抽象实现类,统一实现了BeanDefinition接口定义的一部分操作,定义了BeanDefinition很多默认的属性。同时还继承了BeanMetadataAttributeAccessor类,BeanMetadataAttributeAccessor类又继承自AttributeAccessorSupport,所以AbstractBeanDefinition还同时具备对元数据访问的各种方法实现。正是在AbstractBeanDefinition基础上,Spring又衍生出了一系列的BeanDefinition。Spring框架的设计中,充满了这种通过上下继承关系来对基类进行功能扩充与功能分隔的类体系。

AbstractBeanDefinition上衍生出来的几个类:

  • RootBeanDefinition类: 这是一个可以合并的BeanDefinition,在Spring容器运行期间,容器会对BeanDefinition进行合并,以保证BeanDefinition是最新的,返回的就是RootBeanDefinition。
  • GenericBeanDefinition类: Spring2.5之后出现的通用BeanDefinition实现类,用来操作和返回BeanDefinition,可以灵活设置自己的parentBeanDefinition,而不像RootBeanDefinition一样硬编码,一般我们通过注解配置的bean以及我们的配置类(除@Bean外)的BeanDefiniton类型都是GenericBeanDefinition
  • ChildBeanDefinition类: 现在已经被GenericBeanDefinition所替代了。GenericBeanDefinition相对于ChildBeanDefinition更灵活,GenericBeanDefinition不需要强制指定parentName

关于BeanBeanDefinition的区别,就说到这,最后再次重申本文章的内容:本文主要以分析Spring源码模块脉络为主,主要带领读者理清Spring运行的流程和脉络,不会深究一些知识细节,避免陷入细节无法自拔,所以虽然BeanDefinition很重要,是Spring的基石,但还是以介绍为主,并不会深入进入分析源码,意在最快时间带领读者进入Spring的脉络与流程,如果对某个接口或者某个实现类的逻辑比较感兴趣,可以自行阅读对应的源码。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • spring框架通过xml以及注解方式注册BeanDefinition的流程全链路分析

    在上一章节中,主要介绍了SpringIoC、依赖注入和Spring中的Bean与BeanDefinition。可能部分读者还是比较迷茫,BeanDefiniti...

    星如月勿忘初心
  • Spring框架源码分析(IoC):Resource、ResourceLoader和容器之间的关系

    Resource接口定义了资源常见的操作,抽象出了一些通用方法,再由不同的实现类去自定义。直接上Resource源码:

    星如月勿忘初心
  • 剑指Offer题解

    在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少存在一个数字是重复的。 请找出数组中任意一个重复的数字,但不能修改输入的数组。 例如输...

    星如月勿忘初心
  • 选择使用Spring框架的原因(Spring框架为企业级开发带来的好处有哪些)?

    唐怀瑟
  • Spring IOC概念

    反转是中思想,将类的实例化和管理交给Spring(包括关系处理垃圾回收等),我们只需要去Spring这个容器中取即可

    大话swift
  • EJB3最新的EJB标准

    Spring可以部分简化EJB本地和远程调用。EJB3分消息驱动Bean、有、无状态Bean和实体Bean。分别服务于应用层和持久层。JBoss的EJB3实体...

    py3study
  • 想要学会Spring源码,你必知必会的BeanDefinition原理!

    这是一个经典的面试题,什么是java Object?万物皆对象,在Java内部所有的类,经过创建之后都可以称之为一个对象,SpringBean也是一个java ...

    止术
  • Spring实时统计与监控Spring-Dashboard及Spring集群Terracotta for Spring

    Spring实时统计与监控Spring-Dashboard及Spring集群Terracotta for Spring

    阿敏总司令
  • JavaEE开发之Spring中的依赖注入与AOP编程

    上篇博客我们系统的聊了《JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建》,并在之前的博客中我们聊了依赖注入的相关东西,并且使...

    lizelu
  • spring杂碎

    Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理

    陈灬大灬海

扫码关注云+社区

领取腾讯云代金券