什么是IoC Container
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供
BeanFactory and ApplicationContext
BeanFactory 提供了最基础的Bean管理功能
ApplicationContext 继承自BeanFactory并新增了一些功能
BeanFactory 和 ApplicationContext 都是接口,他们各自有许多不同的实现类
BeanDefinition
BeanDefinition 是IoC Container中重要的数据结构,他抽象了对Bean的定义。IoC Container实则是管理了一堆BeanDefinition。IoC容器对Bean的管理和依赖注入功能的实现,是通过对其持有的BeanDefinition进行各种相关操作来完成的。
如何创造一个BeanFactory IoC Container
* 以DefaultListableBeanFactory为例
指定BeanDefinition的信息来源,传入一个或多个xml文件的路径
创建BeanFactory
创建BeanDefinitionReader,并注册给BeanFactory
用BeanDefinitionReader解析配置文件,生成BeanDefinition
如何创造一个ApplicationContext IoC Container
以ClassPathXmlApplicationContext为例
ApplicationContext在BeanFactory的基础上添加的附加功能,继承了MessageSource、ApplicationEventPublisher、ResourcePatternResolver等接口。
因为ApplicationContext继承了拥有各种不同的Resource读取器,所以不需要我们手动创建。
IoC Container的初始化
初始化就是BeanDefinition的Resource定位、载入和注册三个基本过程。
Resource定位过程
由ResourceLoader通过统一的Resource接口来完成
在文件系统中的Bean定义信息可以使用FileSystemResource来进行抽象
在类路径中的Bean定义信息可以使用前面提到的ClassPathResource来使用
BeanDefinition的载入
这个载入过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。
向IoC容器注册这些BeanDefinition
调用BeanDefinitionRegistry接口,在IoC容器内部将BeanDefinition注入到一个HashMap中。
IoC Container的依赖注入
在IoC容器初始化过程中,一般不包含Bean依赖注入的实现。Bean的载入和依赖注入是两个独立的过程。
依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。但有一个例外值得注意,在使用IoC容器时有一个预实例化的配置,通过这个预实例化的配置(具体来说,可以通过为Bean定义信息中的lazyinit属性),用户可以对容器初始化过程作一个微小的控制,从而改变这个被设置了lazyinit属性的Bean的依赖注入过程。举例来说,如果我们对某个Bean设置了lazyinit属性,那么这个Bean的依赖注入在IoC容器初始化时就预先完成了,而不需要等到整个初始化完成以后,第一次使用getBean时才会触发。
在getBean方法中,首先会去搜索这个Bean是否已经存在,如果存在就直接使用。(注意这里默认设置IoC Container为单例模式,也可以更换)
如果没有存在,就会用BeanName调取对应的BeanDefinition,再根据BeanDefinition中定义的依赖Bean去递归的方式寻找依赖的Bean,直到这个Bean并没有依赖的Bean。所以getBean时对应的依赖也已经注入。
IoC Bean作用域
在一个BeanFactory或ApplicationContext下
singleton每次都是同一个实例
prototype每次getBean一个实例
当用户使用支持 Web 的 ApplicationContext 时
request每一个request一个实例
session每一个request一个实例
Bean在容器内的生命周期
Spring 容器根据配置中的 BeanDefinition实例化Bean;
Spring 使用依赖注入填充所有属性,如 Bean 中所定义的配置;
如果 Bean 实现 BeanNameAware 接口,则工厂通过传递 Bean 的 ID 来调用 setBeanName();
如果 Bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory();
如果存在与 Bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法;
如果为 Bean 指定了 init 方法( <bean> 的 init-method 属性),那么将调用它;
最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法;
如果 Bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory();
如果为 Bean 指定了 destroy 方法( <bean> 的 destroy-method 属性),那么将调用它。