spring-framework : 5.2.0.RELEASE
IoC:即控制反转机制。在Spring中的实现表现为IoC容器,属于Spring Core模块最核心的部分。
IoC其实是一种设计思想,其本质就是将对象的创建、依赖关系的管理以及生命周期的的控制交由IoC容器,或者说是框架来管理,解放了码农的双手。
IoC的存在离不开另外一个设计思想——依赖注入(DI)。
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中的容器类。
在Spring中,Bean是一等公民,我们常说的对象在Spring中就描述为Bean。Bean的本质其实就是Java对象,是我们期望从Spring容器中获取到的实例。
而如果我们去阅读Spring的源码,会发现在Spring中大量操作的是一种名为BeanDefinition的类,而不是Bean。在Spring中,BeanDefinition是对Bean的定义与描述,Bean和BeanDefinition的关系有点像装饰器模式的增强:
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
。关于Bean
和BeanDefinition
的区别,就说到这,最后再次重申本文章的内容:本文主要以分析Spring源码模块脉络为主,主要带领读者理清Spring运行的流程和脉络,不会深究一些知识细节,避免陷入细节无法自拔,所以虽然BeanDefinition很重要,是Spring的基石,但还是以介绍为主,并不会深入进入分析源码,意在最快时间带领读者进入Spring的脉络与流程,如果对某个接口或者某个实现类的逻辑比较感兴趣,可以自行阅读对应的源码。