什么是控制反转 (IoC) Inverse of Control?
IoC包括两方面的内容: (1)控制 (2)反转
"控制" 指对某一个接口的具体实现类选择的控制权
"反转" 指这种控制权从调用者手上移除
控制反转就是指, 某一接口具体实现类的选择控制权从调用类移除, 转交给第三方决定 ,第三方可以是Spring容器.
Bean工厂 (com.springframework.beans.factory.BeanFactory) 是Spring 框架最核心的接口. 它提供了高级的 IoC配置机制. BeanFactory管理不同的Java对象, 应用上下文 (com.springframework.context.ApplicationContext) 建立在 BeanFactory 的基础上. 提供了更多面向应用的功能, 更容易创建实际应用. 一般称 BeanFactory 为 IoC容器, ApplicationContext为应用上下文, ApplicationContext也称为 Spring 容器.
BeanFactory 是 Spring框架的基础设施, 面向 Spring本身, ApplicationContext 面向Spring框架 的开发者.
BeanFactory是类的通用工厂, 可以创建并管理各种类的对象. Spring称这些被创建的Java对象为 Bean.
一.BeanFactory的体系结构
对BeanFactory其他接口进行简单说明:
ListableBeanFactory: 该接口定义了访问Bean基本信息的若干方法. 查看Bean的个数, 获取某一Bean的配置名等.
HierarchicalBeanFactory: 父子级联IoC容器的接口, 子容器可通过接口访问父容器.
ConfigurableBeanFactory: 增强了 IoC容器的可定制性. 定义了设置类装载器, 属性编辑器, 容器初始化后置处理器等方法.
AutowireCapableBeanFactory: 定义了容器中的Bean按某种规则进行自动装配的方法.
SingletonBeanRegistry: 定义了允许在运行期间向容器注册单实例Bean的方法.
BeanDefinitionRegistry: Spring配置文件中的每一个<bean>结点元素, 在Spring容器里都通过一个 BeanDefinition对象表示. 描述了Bean的配置信息. BeanDefinitionRegistry提供了向容器手工注册BeanDefinition对象的方法.
二.初始化BeanFactory
XmlBeanDefinitionReader 通过 Resource 装载 Spring配置信息并启动 IoC容器. BeanFactory 启动 IoC容器时, 并不会初始化配置文件中定义的Bean. 初始化动作发生在第一个调用. 对于单实例的Bean (singleton) 来说, BeanFactory 会缓存 Bean实例, 第二次使用 getBean()获取 Bean时, 直接从 IoC容器的缓存中获取Bean实例.
Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存容器. 它是一个用HashMap实现的缓存器. 单实例的Bean 以 beanName 为键保存在这个 HashMap中.
三.BeanFactory中 Bean 的生命周期
在Spring中, 可以从两个层面定义 Bean 的生命周期: 第一个层面是Bean的作用范围; 第二个层面是实例化 Bean 时所经历的一些阶段.
BeanFactory 中 Bean生命周期的完整过程:
具体过程概述:
(1)当调用者向容器请求某一个Bean时, 如果容器注册了 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口, 则在实例化 Bean之前, 将调用接口的postProcessBeforeInstantiation()方法.
(2)根据配置情况实例化 Bean.
(3)如果容器注册了InstantiationAwareBeanPostProcessor接口, 那么在实例化Bean之后, 调用该接口的postProcessAfterInstantiation()方法.
(4)在设置 Bean的每个属性之前调用 InstantiationAwareBeanPostProcessor接口的 postProcessPropertyValues()方法.
(5)调用 Bean的属性设置方法设置属性.
(6)如果 Bean 实现了 org.springframework.beans.factory.BeanNameAware 接口, 则调用 setBeanName()接口方法 , 将配置文件该Bean对应的名称设置到 Bean中.
(7)如果 Bean实现了 org.springframework.beans.factory.BeanFactoryAware 接口, 则调用 setBeanFactory()接口方法, 将BeanFactory实例设置到容器中.
(8)如果 BeanFactory 装配了 org.springframework.beans.factory.config.BeanPostProcessor 后处理器, 则将调用 BeanPostProcessor 的 Object postProcessBeforeInitialization(Object bean, String beanName) 方法对Bean进行加工操作. 入参bean是当前正在处理的 Bean, beanName是当前Bean的配置名, 返回的对象为加工处理后的Bean.
(9)如果 Bean实现了 InitializingBean接口, 则将调用接口的 afterPropertiesSet()方法.
(10)如果在 <bean>中通过 init-method 属性定义了初始化方法, 则将执行这个方法.
(11)再次调用 BeanPostProcessor 后处理器的 Object postProcessAfterInitializtion(Object bean, String beanName)方法. 容器再次对Bean进行加工处理.
(12)如果在 <bean>中指定 Bean的作用范围为 scope="prototype" , 则将 Bean 返回给调用者, 调用者负责 Bean后续生命的管理. Spring不再管理这个 Bean的生命周期.
如果 Bean 的作用范围为 scope="singleton" , 则将 Bean 放入 Spring IoC容器的缓存池, 并将 Bean引用返回给调用者. Spring 继续对这些Bean进行后续生命周期的管理.
(13)对于 scrop="singleton" 的Bean, 当容器关闭时, 将触发Spring对Bean后续生命周期的管理工作, 如果 Bean 实现了DisposableBean 接口, 则将调用接口的 destory() 方法.
(14)对于 scrop="singleton" 的 Bean, 如果 <bean>的 destory-method 属性指定了 Bean 的销毁方法. Spring 将执行 Bean的这个方法. 完成对 Bean 资源的释放.
#####Bean 的完整生命周期大概总结:
从 Spring 容器着手实例化 Bean 开始, 到最终销毁 Bean, 经历了很多关键点, 每个关键点都涉及到特定方法的调用.
Bean自身的方法: Bean构造函数实例化Bean, Bean的setter方法设置 Bean的属性. 通过 <bean>的init-method 和 destory-method属性所指定的方法.
Bean级生命周期接口方法: 如 BeanNameAware, BeanFactoryAware, InitializingBean 和 DisposableBean, 这些接口方法由Bean类直接实现.
容器级生命周期方法: 由 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 接口实现, 一般称它们的实现类为"后处理器", 后处理器接口不由 Bean 本身实现, 实现类以容器附加装载的形式注册到 Spring 容器中. 并通过接口反射为 Spring 容器扫描识别. 当Spring创建任何容器时, 这些后处理器都会发生作用, 后处理器的影响是全局的.InstantiationAwareBeanPostProcessor 其实是 BeanPostProcessor 接口的子接口, Spring 为其提供了一个适配器类 InstantiationAwareBeanPostProcessorAdapter. 方便的扩展该适配器以定义其实现类.
四. Bean生命周期的实例
实现所有Bean级生命周期接口, 并定义初始化和销毁方法.
实现容器级接口
MyInstantationAwareBeanPostProcessor通过扩展 InstantationAwareBeanPostProcessor接口 适配器 InstantationAwareBeanPostProcessorAdapter 提供实现; MyBeanPostProcessor 通过实现 BeanPostProcessor接口为后处理器.
装配配置文件, 并创建BeanFactory容器, 将 MyInstantstionAwareBeanPostProcessor 和 MyBeanPostProcessor这两个后处理器注册到容器中.
用于注册后处理器的 addBeanPostProcessor() 方法是在 ConfigurableBeanFactory接口中定义的, 所以必须进行强转, 后处理器的注册顺序和实际调用顺序是无关的, 在具有多个后处理器的情况下, 必须通过实现 org.springframework.core.Ordered 接口来确定调用顺序.