文章目录
目录
前言
主要介绍了Ioc容器初始化两阶段,容器初始化和bean的实例生成。
一、容器初始化阶段
- 基本流程
- 得到Configuration MetaData配置信息,要么是直接编码的,或者XML配置文件,或者是注解,如果是配置文件就需要BeanDefinitionReader帮助我们解析配置信息,然后将信息装配到BeanDefinition,注册到BeanDefinitionRegistry,这样容器启动工作就完成了
- BeanFactoryPostProcessor---容器初始化阶段后处理扩展机制
- 功能
- BeanFactoryPostProcessor可以实现容器的扩展,在容器初始化阶段的最后加入一道后处理工序,在后处理过程中对BeanDefinition中的信息做一些修改
- 写自定义的BeanFactoryPostProcessor需要实现BeanFactoryPostProcessor接口,如果容器里有很多BeanFactoryPostProcessor,且他们的执行顺序比较重要,还需要同时实现Ordered接口,让BeanFactoryPostProcessor按照设定的顺序执行
- 配置以使用BeanPostProcessor
- BeanFactory
- 需要手动装配所有BeanFactoryPostProcessor,实例化BeanFactoryPostProcessor,然后调用其PostProcessBeanFactory方法,对传入的beanfactory进行后处理
- ApplicationContext
- 只需要在配置信息里配置需要的BeanFactoryPostProcessor,ApplicationContext会自动识别并应用它
- BeanFactory
- 常用BeanFactoryPostProcessor
- PropertyPlaceholderCofigurer
- 在配置文件里允许使用占位符(&{property})配置一些可能经常修改的系统管理信息,这些信息单独配置在properties文件里,在容器初始化前处理阶段都完成后,这些信息以占位符形式存在,容器进入后处理阶段,PropertyPlacehoderConfigurer作为BeanFactoryPostProcessor被应用,由它将占位符信息替换为properties文件里的实际信息,这样容器进入Bean实例化阶段时,这些信息就是装备好的了
- PropertyPlacehoderConfigurer不仅仅从properties文件里加载配置项,当在properties文件里找不到需要的配置项时,还会去检查Java的System类里的Properties,默认采用FALLBACK模式
- PropertyOverrideConfigurer
- PropertyOverrideConfigurer的properties文件里,通过beanName.propertyName=xxx,可以将配置文件里id为beanName的bean中名字为PropertyName的property的值替换为xxx
- 将PropertyOverrideConfigerer注册到容器里,在容器后处理时,容器中bean的一些property值可能会被PropertyOverrideCongurer对应的properties文件中定义的值给覆盖掉
- CustomEditorConfigurer
- 通过CustomEditorConfigurer注册自定义的PropertyEditor来补充容器里默认的PropertyEditor,保存到BeanDefinition里以便后期Bean实例化阶段的属性注入过程中被BeanWrapper拿出来使用
处理配置文件中的数据类型与真正业务对象所定义的数据类型转换 - 每一个数据类型都有对应的一个propertyEditor用于实现将配置文件里拿到的字符串转换成我们需要的实际对象的类型的功能,String内部通过JavaBean的PropertyEditor来完成String类型到其他类型的转换,JavaBean里有的PropertyEditor会被容器默认加载使用,而通过CustomEditorConfigurer可以向容器里注册用于实现特定对象类型转换的自定义PropertyEditor
- 通过CustomEditorConfigurer注册自定义的PropertyEditor来补充容器里默认的PropertyEditor,保存到BeanDefinition里以便后期Bean实例化阶段的属性注入过程中被BeanWrapper拿出来使用
- CustomScopeConfigurer
- 完成自定义scope的注册
- PropertyPlaceholderCofigurer
- 功能
二、Bean实例化阶段
- 基本流程
- 请求方getBean或者因为依赖关系需要隐式的getbean时,会触发Bean的实例化
- singleton的bean:容器先检查对象是否初始化,如果已经有了实例对象,会直接返回这个实例对象,如果没有会根据BeanDefinition的中的信息实例化对象,并为其注入依赖,如果对象实现某些回调接口,也会根据回调接口的请求来装配它,对象装配完成返回给请求方使用
- prototype的bean:容器每次遇到getbean都创建一个新的实例对象返回
- BeanPostProcessor---Bean实例化阶段扩展点
- 功能
- 对所有符合条件的实例化后对象实例进行处理
- Ioc中
- Aware接口依赖注入
- ApplicationContextAwareProcessor在ApplicationCon容器里实现Aware依赖注入
- 通过BeanPostProcessorBeforeInitialization方法对实现了Aware接口的bean进行处理,即进行Aware的依赖注入
- 基于注解的依赖注入
- AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor通过BeanPostProcessorBeforeInitialization方法遍历所有对象,通过反射拿到其信息,找到被注解标注的属性或者方法进行依赖注入
- Aware接口依赖注入
- AOP中
- 替换当前对象实例或者字节码增强当前对象实例,AOP一般使用它来为对象生成相应的代理对象,比如BeanNameAutoProxyCreator
- 功能
- bean的生命周期
- 实例化对象---两种策略模式
- SimpleInstantiationSrategy
- 利用反射实例化bean,不支持方法注入
- CglbSubclassingInstantiationSrategy
- 继承了SimpleInstantiationSrategy的反射实例化方式
- 同时可以利用动态字节码功能动态生成某个类的子类,支持方法注入
- SimpleInstantiationSrategy
- 设置属性&依赖注入---BeanWrapper
- 实例化后的对象要被BeanWrapper包裹,返回一个BeanWrapper实例,spring通过这个BeanWrapper实例去设置对象属性,比直接用反射方便的多
- BeanWrapper继承了PropertyAccessor,PropertyEditorRegistry,通过PropertyAccessor可以统一的对对象属性进行访问,通过PropertyEdition可以将字符串转换成需要的数据类型
- 容器注入Aware接口相关依赖---BeanPostProcessorBeforeInitialization前置处理
- beanFactory
- 代码方式通过addBeanPostProcessor方法手动将beanPostProcessor实现类注入到beanfactory容器里
- 在BeanPostProcessBeforeInitialization方法里对符合条件的实例化后对象进行处理,设置Aware依赖
- 一个bean实现BeanFactoryAware接口的话,BeanFactory容器会把自身注入到该对象实例
- 一个bean实现BeanClassLoaderAware接口,beanFactory容器会把ClassLoader注册到该对象实例
- ApplicationContext
- BeanPostProcessor实现类ApplicationContextAwareProcessor会被提前注入到ApplicationContext容器
- 通过BeanPostProcessorBeforeInitialization方法,对符合条件的实例化后对象处理,设置Aware依赖
- 一个bean实现了ResourceLoderAware接口,ApplicationContext容器会把自身注册该对象实例
- 一个bean实现了ApplicationEventPublisherAware接口,ApplicationContext容器会把自身注册该对象实例
ApplicationContext实现了ApplicationEventPublisher接口就代表它可以作为一个ApplicationEventPubbulisher使用
- beanFactory
- InitializingBean / init-method
- 检查该bean是否实现InitializingBean接口,如果是会调用AfterPropertiesSet方法,在该方法里会对一些依赖注入后但是还不能直接投入使用的对象进行一些处理
- 可以通过在配置文件里设置bean的init-method配置实现,或者设置beans的default-init-method实现,容器会调用设置的Init-method方法进行对象的配置,相比于InitilazingBean的afterPropertiesSet方法更方便
- BeanPostProcessorAfterInitilization后置处理
- DisposableBean / destroy-method
- 为什么需要定义它
- 对于prototype的bean,提交给请求者后容器不再管理它的生命周期,但是对于singleton的bean,容器关闭时,需要将他们给杀掉
- 检查singleton的bean是否实现了DisposableBean接口,或者通过destroy-method配置了自定义的对象销毁方法
- 对于自定义scope的对象需要我们主动去告知容器在哪个时刻去销毁它们
- 注册好相应的DisposableBean或者destroy-method的回调接口后,对象投入使用
- 什么时候调用它
- 容器是不知道什么时候需要调用对象销毁方法的,我们需要主动告知容器在哪个时刻去执行销毁方法
- 对于singleton的bean会在容器关闭时销毁,对于自定义scope的bean需要我们自己想好什么时候销毁并且告知容器
- 容器怎么调用销毁方法
- BeanFactory
- 通过ConfigurableListableBeanFactory提供的distroysingletons方法触发销毁对象行为
- ApplicationContext
- AbstractApplicationContext为我们提供了registerShutDownHook方法,可以调用自定义销毁逻辑以及ApplicationContext相关的事件发布
- BeanFactory
- 为什么需要定义它