启动流程

Spring IoC启动流程与循环依赖处理

image

Spring IoC容器的整个工作流程大致可以分为两个阶段:容器启动阶段与Bean的实例化阶段。

  • 容器启动时,会通过某种途径加载ConfigurationMetaData。除了代码方式比较直接外,在大部分情况下,容器需要依赖某些工具类,比如:BeanDefinitionReader,BeanDefinitionReader会对加载的ConfigurationMetaData进行解析和分析,并将分析后的信息组装为相应的BeanDefinition,最后把这些保存了bean定义的BeanDefinition,注册到相应的BeanDefinitionRegistry,这样容器的启动工作就完成了。这个阶段主要完成一些准备性工作,更侧重于bean对象管理信息的收集,当然一些验证性或者辅助性的工作也在这一阶段完成。

  • 经过第一阶段,所有bean定义都通过BeanDefinition的方式注册到BeanDefinitionRegistry中,当某个请求通过容器的getBean方法请求某个对象,或者因为依赖关系容器需要隐式的调用getBean时,就会触发第二阶段的活动:容器会首先检查所请求的对象之前是否已经实例化完成。如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。当该对象装配完毕后,容器会立即将其返回给请求方法使用。

BeanFactory只是Spring IoC容器的一种实现,如果没有特殊指定,它采用采用延迟初始化策略:只有当访问容器中的某个对象时,才对该对象进行初始化和依赖注入操作。而在实际场景下,我们更多的使用另外一种类型的容器:ApplicationContext,它构建在BeanFactory之上,属于更高级的容器,除了具有BeanFactory的所有能力之外,还提供对事件监听机制以及国际化的支持等。它管理的bean,在容器启动时全部完成初始化和依赖注入操作。

Spring Boot

private void initialize(Object[] sources) {
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }

    // 判断是否是 Web 项目
    this.webEnvironment = deduceWebEnvironment();

    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

    // 找到入口类
    this.mainApplicationClass = deduceMainApplicationClass();

}

初始化流程中最重要的就是通过SpringFactoriesLoader找到spring.factories文件中配置的ApplicationContextInitializerApplicationListener两个接口的实现类名称,以便后期构造相应的实例。ApplicationContextInitializer的主要目的是在ConfigurableApplicationContextrefresh之前,对ConfigurableApplicationContext实例做进一步的设置或处理。ConfigurableApplicationContext继承自ApplicationContext,其主要提供了对ApplicationContext进行设置的能力。

上一页
下一页