控制反转
Spring IoC
的IoC
全称是"Inversion of Control",译:控制反转数据结构
"控制反转"又称"依赖反转"编码
DI
全称是"Dependency Injection",译:依赖注入设计
使用控制反转,依赖注入后,当建立对象时,由一个调度系统将其所依赖的对象的引用传递给它(这些对象也都来自于调度系统所管理的对象),即依赖被注入到对象中。因此,控制反转是关于一个对象如何获取它所依赖的对象的引用code
上述的调度系统是应用平台,具体来讲是IoC
容器。经过使用IoC
容器,对象依赖关系的管理被反转了,转到IoC
容器中来了,对象之间的相互依赖关系由IoC
容器进行管理,并由IoC
容器完成对象的注入xml
IoC容器的核心数据结构
BeanDefinition
是IoC
容器的核心数据结构。又称"Bean定义信息"。是建立Bean
实例时所使用的模板对象
Bean
是容器管理的对象的统称blog
容器在建立Bean
实例以前会先建立BeanDefinition
对象,它保存了Bean
的定义信息,例如Bean
的名字,类型,是单实例仍是多实例,是否是懒加载,所依赖的其余对象有哪些等接口
IoC容器的设计与实现
IoC
容器有两个系列生命周期
一个是实现BeanFactory
接口的简单容器系列,这个系列的容器能实现容器的最基本的功能。又称"Bean工厂"事件
一个是实现ApplicationContext
接口的高级容器系列,它是容器的高级形态。又称"应用上下文"或"上下文"。上下文在简单容器的基础上又增长了许多新功能
Spring IoC容器的设计
下面这张图描述的IoC
容器的接口设计图,IoC
容器的实现类就是以容器的接口设计为基础实现的
设计主线
- 以
BeanFactory
为核心。从BeanFactory
到HierarchicalBeanFactory
再到ConfigurableBeanFactory
。这是一条主要的BeanFactory
类型容器的设计路线 - 以
ApplicationContext
为核心。从BeanFactory
到ListableBeanFactory
到ApplicationContext
,再到ConfigurableApplicationContext
或WebApplicationContext
。咱们经常使用的上下文基本都是ConfigurableApplicationContext
或WebApplicationContext
的实现类
咱们经常使用的BeanFactory
的实现类是DefaultListableBeanFactory
。同时,以这个实现类为基础,又有许多应用于不一样场景下的子类bean工厂。不过咱们一般直接使用DefaultListableBeanFactory
咱们经常使用的ApplicationContext
的实现类是AbstractApplicationContext
的子类。这个抽象类包含了容器的初始化方法refresh()
。
AbstractApplicationContext
实现的是ConfigurableApplicationContext
接口。
BeanFactory的设计原理
这些接口方法定义出了一个基本的IoC
容器
boolean containsBean(String name);
容器中是否有名为name
的Bean
String[] getAliases(String name);
查询Bean
的全部别名getBean()
有多个重载方法,是从容器中获取Bean
实例的方法(此方法包含若是获取不到就建立一个Bean
实例的流程)boolean isSingleton(String name);
返回Bean
是不是单实例boolean isPrototype(String name)
返回Bean
是不是多实例(Bean
是单实例仍是多实例,这些信息保存在对应的BeanDefinition
对象中)- ...
这些方法提供了容器最基本的功能
ApplicationContext的设计原理
ApplicationContext
除了实现了BeanFactory
外还实现了其余接口,为容器添加了其余功能
MessageSource
信息源。支持国际化功能的实现ResourceLoader
访问资源。用于获取Bean
的定义信息所在的资源,为建立BeanDefinition
对象作准备ApplicationEventPublisher
发布事件。能够在上下文中,在Bean
的生命周期中发布事件- ...
容器初始化流程
首先,由编码者使用某种形式编写Bean
的配置信息,例如在.xml文件中写<bean>
标签配置Bean
而后,启动容器进行初始化。容器初始化大体分三步
BeanDefinition
的Resource
定位(定位Bean
配置信息所在位置)- 载入
BeanDefinition
(建立BeanDefinition
对象) - 向容器注册
BeanDefinition
对象(在容器内部将对象put到一个容器持有的map对象中)
在第一次调用容器的getBean()
方法(BeanFactory
中定义的方法)获取Bean
对象时,若是对象还未被实例化,就获取对应的BeanDefinition
对象,并使用它做为模板建立实例对象
再容器完成初始化后,调用refresh()
方法刷新容器。方法执行完后容器即可以使用
ps:容器初始化的流程可能在refresh()
方法外执行,也可能在refresh()
方法内执行