IoC容器体系
IoC容器是Spring的核⼼模块,是抽象了对象管理、依赖关系管理的框架解决⽅案。<br>Spring IoC 容器继承体系需要使⽤哪个层次⽤哪个层次即可。不是把所有接口都放在BeanFactory<br>ApplicationContext 还继承了ResourceLoader、MessageSource<br>
Bean⽣命周期关键时机点
详细见代码。创建⼀个类 Bean ,让其实现⼏个特殊的接⼝,并分别在接⼝实现的构造器、接⼝⽅法中<br>断点,观察线程调⽤栈,分析出 Bean 对象创建和管理关键点的触发时机。
根据上⾯的调试分析,我们发现 Bean对象创建的⼏个关键时机点代码层级的调⽤都在<br>AbstractApplicationContext 类 的 refresh ⽅法中,可⻅这个⽅法对于Spring IoC 容器初始化来说相当<br>关键,汇总如下:<br>构造器 - refresh#finishBeanFactoryInitialization(beanFactory)(beanFactory)<br>BeanFactoryPostProcessor 初始化refresh#invokeBeanFactoryPostProcessors(beanFactory)<br>BeanFactoryPostProcessor ⽅法调⽤refresh#invokeBeanFactoryPostProcessors(beanFactory)<br>BeanPostProcessor 初始化registerBeanPostProcessors(beanFactory)<br>BeanPostProcessor ⽅法调⽤refresh#finishBeanFactoryInitialization(beanFactory)<br>
子主题
IoC容器初始化主流程(refresh)
第⼀步:刷新前的预处理 prepareRefresh();
第⼆步:获取BeanFactory;默认实现是DefaultListableBeanFactory<br>加载BeanDefition 并注册到 BeanDefitionRegistry<br>ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();<br>
第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加<br>载器等)<br>prepareBeanFactory(beanFactory);
第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作<br>postProcessBeanFactory(beanFactory);
第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean<br>invokeBeanFactoryPostProcessors(beanFactory);
第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执<br>⾏<br>registerBeanPostProcessors(beanFactory);
第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);<br>initMessageSource();
第⼋步:初始化事件派发器<br>initApplicationEventMulticaster();
第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑<br>onRefresh();
第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean<br>registerListeners();
第⼗⼀步:<br>初始化所有剩下的⾮懒加载的单例bean<br>初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)<br>填充属性<br>初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)<br>调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处<br>finishBeanFactoryInitialization(beanFactory);<br>
第⼗⼆步:<br>完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事<br>件 (ContextRefreshedEvent)<br>finishRefresh();<br>
BeanFactory创建流程
获取BeanFactory⼦流程
BeanDefinition加载解析及注册⼦流程
Resource定位:指对BeanDefinition的资源定位过程。通俗讲就是找到定义Javabean信息的XML⽂<br>件,并将其封装成Resource对象。
子主题
BeanDefinition载⼊ :把⽤户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数<br>据结构就是BeanDefinition。
Bean创建流程
finishBeanFactoryInitialization,创建子流程入口<br>beanFactory.preInstantiateSingletons() 实例化所有,立即加载单例bean<br>最后跟到AbstractBeanFactory类的doGetBean⽅法<br>最后调用 initializeBean
lazy-init 延迟加载机制原理
lazy-init 延迟加载机制分析
<ol><li>Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring能够识别的BeanDefinition并存到Hashmap⾥供下⾯的初始化时⽤,然后对每个BeanDefinition 进⾏处理。</li><li>如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进⾏初始化并依赖注⼊。最后通过外部getBean调用。<br>preInstantiateSingletons() 下 !bd.isLazyInit() 判断懒加载,是否需要初始化。普通Bean 直接调用getBean<br></li></ol>
总结
<ol><li>对于被修饰为lazy-init的bean Spring 容器初始化阶段不会进⾏ init 并且依赖注⼊,当第⼀次<br>进⾏getBean时候才进⾏初始化并依赖注⼊</li><li>对于⾮懒加载的bean,getBean的时候会从缓存⾥头获取,因为容器初始化阶段 Bean 已经<br>初始化完成并缓存了起来</li></ol>