站在设计者的角度考虑设计IOC容器
- 加载Bean的配置(比如xml配置)- 比如不同类型资源的加载,解析成生成统一Bean的定义
- 根据Bean的定义加载生成Bean的实例,并放置在Bean容器中- 比如Bean的依赖注入,Bean的嵌套,Bean存放(缓存)等
- 除了基础Bean外,还有常规针对企业级业务的特别Bean- 比如国际化Message,事件Event等生成特殊的类结构去支撑
- 对容器中的Bean提供统一的管理和调用- 比如用工厂模式管理,提供方法根据名字/类的类型等从容器中获取Bean
一、IOC初始化流程图
Class (UserService)—>实例化 —> 对象 ---->属性填充(依赖注入)-----> 初始化(实现InitializingBean) ---->AOP -->代理对象 -----> bean
1.1、如何将Bean从XML配置文件解析后放到IOC容器中;
背景:
SpringIOC容器它会以某种方式,加载配置文件中的 信息,将其解析为一个个的BeanDefinition.之后将BeanDefinition注册到容器之中。Spring IOC容器在实现的时候经过的过程可以使用如下图片表示
分为两个主要部分:
其一 :容器启动阶段
其二:bean实例化阶段。
在容器的启动阶段主要做的是一些信息收集的过程(主要依赖于工具类BeanDefinitionReader),将收集的信息组成BeanDefinition.将BeanDefinition注册到相应的BeaneanRegistry。
Bean实例化的过程在请求方通过容器的getBean方法明确请求某个对象时候触发/隐式依赖关系调用时候也会触发该动作。此阶段做的操作主要是判断当前的请求对象是否已经被实例化过了。根据情况进行注入,当该对象实现某些回调接口,也会根据回调函数接口装配它。
目标:
分析Spring如何将配置文件解析,(以XML配置文件为例)通过加载解析,生成BeanDefination 并注册到IOC容器中;
https://www.pdai.tech/md/spring/spring-x-framework-ioc-source-2.html
1.2、BeanFactory和 BeanRegistry:IOC功能规范和Bean的注册。
Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,这是IOC容器的基础;在顶层的结构设计主要围绕着BeanFactory和xxxRegistry进行:
- BeanFactory: 工厂模式定义了IOC容器的基本功能规范
- BeanRegistry: 向IOC容器手工注册 BeanDefinition 对象的方法
如何将Bean注册到BeanFactory中?BeanRegistry
Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法。
BeanDefinition:各种Bean对象及其相互的关系Bean对象存在依赖嵌套等关系,所以设计者设计了BeanDefinition,它用来对Bean对象及关系定义;我们在理解时只需要抓住如下三个要点:
- BeanDefinition 定义了各种Bean对象及其相互的关系
- BeanDefinitionReader 这是BeanDefinition的解析器
- BeanDefinitionHolder 这是BeanDefination的包装类,用来存储BeanDefinition,name以及aliases等。
1.3、核心组件介绍;
1.3.1、Bean组件
Bean组件定义在Spring的org.springframework.beans包下,解决了以下几个问题:
这个包下的所有类主要解决了三件事:
- Bean的定义
- Bean的创建- Bean的解析
- Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,这是IOC容器的基础;在顶层的结构设计主要围绕着BeanFactory和xxxRegistry进行: - BeanFactory: 工厂模式定义了IOC容器的基本功能规范- BeanRegistry: 向IOC容器手工注册 BeanDefinition 对象的方法
BeanFactory有三个子类: ListableBeanEactory、HierarchicalBeanEactory和AutowirecCapableBeanEactory。目的是为了区分Spring内部对象处理和转化的数据限制。
但是从下图中可以发现最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口
1.3.2、Bean定义:BeanDefinition
这里的BeanDefinition就是我们所说的Spring 的Bean,我们自己定义的各个Bean其实会转换成一个个BeanDefinition存在于Spring的BeanFactory中
publicclassDefaultListableBeanFactoryextendsAbstractAutowireCapableBeanFactoryimplementsConfigurableListableBeanFactory,BeanDefinitionRegistry,Serializable{
BeanDefinition 中保存了我们的Bean信息,比如这个Bean指向的是哪个类、是否是单例的、是否懒加载、这个Bean依赖了哪些Bean等等,
1.3.3、Context组件:
Context在Spring的org.springframework.context包下
Context模块构建于Core和Beans模块基础之上,提供了一种类似于INDJ注册器的框架式的对象访问方法.Context模块继承了Beans的特性,为Spring核心提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对Context的透明创建的支持
Applicationcontext是Context的顶级父类
IoC容器的接口类是ApplicationContext,很显然它必然继承BeanFactory对Bean规范(最基本的ioc容器的实现)进行定义。而ApplicationContext表示的是应用的上下文,除了对Bean的管理外,还至少应该包含了
- 访问资源: 对不同方式的Bean配置(即资源)进行加载。(实现ResourcePatternResolver接口)
- 国际化: 支持信息源,可以实现国际化。(实现MessageSource接口)
- 应用事件: 支持应用事件。(实现ApplicationEventPublisher接口)
1.3.4、ApplicationContext 的子类主要包含两个方面:
1.ConfigurableApplicationContext表示该Context是可修改的,也就是在构建Context 中用户可以动态添加或修改已有的配置信息
2.WebApplicationContext顾名思义,就是为web准备的Context他可以直接访问到 ServletContext
再往下分就是按照构建Context的文件类型,接着就是访问Context的方式。这样一级一级构成了完整的Context等级层次。总体来说ApplicationContext必须要完成以下几件事:
- 标识一个应用环境
- 利用BeanFactory创建Bean对象·保存对象关系表
- 能够捕获各种事件
面试题:简述Spring 前置处理器和后置处理器;
请参考:
https://blog.csdn.net/Elsa15/article/details/108647939
后置处理器是一种拓展机制,贯穿Spring Bean的生命周期
BeanPostProcessore
后置处理器分为两类:
实例后的对象,初始化之前BeanBeforePostProcessor
实例后的对象,初始化之后BeanAfterPostProcessor
思考:
什么是前置处理器?
BeanFactoryPostProcess
前置:实例化对象之前
这个机制允许我们在实例化相应对象之前对注册到容器中的BeanDefinition的存储信息进行修改。可以根据这个机制对Bean增加其它信息。修改Bean定义的某些属性值。
想自定义前置处理器需要实现BeanFactoryPostProcess接口。当一个容器存在多种前置处理的时候,可以让前置处理器的实现类同时继承Ordered接口。
Spring容器提供了数种现成的前置处理器,常见的如:
- ropertyPlaceholderConfigurer:允许在xml文件中使用占位符。将占位符代表的资源单独配置到简单的Properties文件中加载
- PropertyOverrideConfigurer:不同于PropertyPlaceholderConfigurer的是,该类用于处理容器中的默认值覆为新值的场景
- CustomEditorConfigurer:此前的两个前置处理器处理的均是BeanDefinition.通过把BeanDefinition的数据修改达到目的。CustomEditorConfigurer没有对BeanDefinition做任何变动。负责的是将后期会用到的信息注册到容器之中。例如将类型转换器注册到BeanDefinition中。供BeanDefinition将获取到的String类型参数转换为需要的类型。
实例化和初始化的区别?
1、实例化----实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中。
2、初始化----初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性。
Bean后置处理器:BeanPostProcessor
BeanPostProcessor是Spring lOC容器给我们提供的一个扩展接口
实现该接口,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些处理逻辑
后置处理器的作用是为了加一些监控bean的操作,通过代理原有bean 增强bean操作。
运行顺序:
SpringIOC 实例化Bean
调用BeanPostProcessor的postProcessBeforeInitialization方法
调用Bean实例的初始化方法;
调用BeanPostProcessor的postProcessAfterInitialization方法
二、Bean的生命周期
Bean生命周期的整个执行过程描述如下。
1、根据配置情况调用Bean构造方法或工厂方法实例化 Bean。
2、利用依赖注入完成Bean中所有属性值的配置注入。
3、如果Bean 实现了BeanNameAware 接口,则 Spring调用Bean的setBeanName()方法传入当前Bean的id值。
4、如果Bean实现了BeanFactoryAware 接口,则 Spring 调用setBeanFactory()方法传入当前工厂实例的引用。
5、如果Bean 实现了ApplicationContextAware 接口,则 Spring调用setApplicationContext()方法传入当前ApplicationContext 实例的引用。
6、如果BeanPostProcessor 和Bean关联,则 Spring将调用该接口的预初始化方法postProcessBeforelnitialzation()对 Bean进行加工操作,此处非常重要,Spring的AOP就是利用它实现的。
7、如果Bean实现了InitializingBean接口,则 Spring将调用afterPropertiesSet()方法。
8、如果在配置文件中通过 init-method属性指定了初始化方法,则调用该初始化方法。
9、如果BeanPostProcessor和 Bean关联,则 Spring将调用该接口的初始化方法、 postProcessAfterlntialization()。此时,Bean已经可以被应用系统使用了。
10、如果在 中指定了该Bean的作用范围为scope=“singleton”,则将该Bean放入Spring IOC的缓存池中,将触发Spring对该Bean 的生命周期管理;如果在中指定了该Bean的作用范围为scope=“prototype”,则将该Bean交给调用者,调用者管理该Bean的生命周期,Spring不再管理该 Bean。
11、如果Bean实现了DisposableBean接口,则 Spring 会调用destory()方法将Spring 中的 Bean销毁; 如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则 Spring将调用该方法。
版权归原作者 Been Doing 所有, 如有侵权,请联系我们删除。