Spring中有两个主要的容器系列:
实现BeanFactory接口的简单容器;
实现ApplicationContext接口的高级容器。
ApplicationContext相对于BeanFactory的好处,ApplicationContext中提供了一系列加载不同Resource的读取器的实现,而DefaultListableBeanFactory需要为它配置特定的读取器才能完成这些功能,
Ioc容器初始化
SpringIoC容器初始化会执行BeanDefinition的Resource定位、载入和注册。通过这个过程使得Spring拥有了所有的bean的定义,为后续bean的创建、自动注入和销毁提供了数据支持。
ApplicationContext的实现在构造函数中通过refresh来启动Ioc容器的初始化
refresh方法在AbstractApplicationContext类中,描述了整个ApplicationContext初始化的过程,比如BeanFactory的更新,MessageResource和PostProcessor的注册等。
refreshBeanFactory是在AbstractRefreshableApplicationContext类中,在这个方法中创建了Ioc容器DefaultListableBeanFactory,在创建Ioc容器之前,如果已经有容器存在,那么需要把已有的容器销毁和关闭,保证在refresh之后使用的是新建立的Ioc容器。这个refresh非常像重启容器
registerBeanDefinition
1.BeanDefinition的Resource定位
即BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成。这个过程类似于容器寻找数据的过程,就像用水桶装水先要找到水一样
2.BeanDefinition的载入
即把用户定义好的Bean表示成Ioc容器内部的数据结构BeanDefinition,BeanDefinition就是POJO对象在Ioc容器中的抽象
3.向Ioc容器注册BeanDefinition
通过调用BeanDefinitionRegistry接口的实现来完成,把载入过程解析得到的BeanDefinition向Ioc容器进行注册,Ioc容器将BeanDefinition注册到一个ConcurrntHashMap中进行管理
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
/** List of names of manually registered singletons, in registration order */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
将
BeanDefinition的Resource定位
Resource并不能由Factory直接使用,通过BeanDefinitionReader来处理
lazy-init属性和预实例化
refresh中的finishBeanFactoryInitialization的方法中,封装了对lazy-init属性的处理,
实际处理是在DefaultListableBeanFactory这个基本容器中的preInstantiateSingletons方法中完成的。与正常的依赖注入的触发相比,只是触发的时间和场合不同,在这里,依赖注入发生在容器执行refresh初始化的过程中,一般的依赖注入发生在Ioc容器初始化完成后,第一次向容器中执行getBean时。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);