Spring - IOC容器的启动流程

89 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


  1. 第一步,首先会执行一些容器刷新前的准备工作,如设置容器启动时间、一些状态标志位等。

  2. 第二步,创建容器对象,其实就是实力话DefaultListableBeanFactory对象,这一步包含了bean定义信息的解析,解析后的属性都封装到DefaultListableBeanFactory的成员属性中了,如我们常见的beanDefinitionMap、beanDefinitionNames;

  3. 第三步,准备Bean工厂,实际上就是设置beanFactory的一些属性;

  4. 第四步, Spring提供了postProcessBeanFactory()方法给我们取扩展,例如我们可以注册一些特殊的BeanPostProcessor后置处理器等操作;

  5. 第五步,执行BeanFactoryPostProcessor后置处理器的postProcessBeanFactory()增强方法,使用三个不同的集合分别存放实现了PriorityOrdered接口、实现了Ordered接口、普通的BeanFactoryPostProcessor,经过排序后,执行BeanFactoryProstProcessor的回调postProcessBeanFactory();

  6. 第六步,注册BeanPostProcessor后置处理器,注意,这里还不会执行BeanPostProcessor对应的增强方法;同样的,使用三个不同的集合分别存放实现了PriorityOrdered接口、实现了Ordered接口、普通的BeanPostProcessor,依次调用beanFactory.addBeanPostProcessor(postProcessor)方法往bean工厂中天假BeanPostProcessor;

  7. 第七步,为上下文初始化MessageSource,即国际化处理;

  8. 第八步,初始化事件多播器,即ApplicationEventMulticaster,为后面的时间发布-监听做准备;

  9. 第九步,提供了一个模版方法onRefresh(),留给子类初始化其他的bean;

  10. 第十步,注册Listener监听器

  11. 第十一步,实例化所有剩下的非懒加载的单例Bean,Bean的生命周期也是从这里开始的。

会获取到之前解析到的所有bean名称集合,按个屌用getBean(beanName)方法,然后经历doGetBean()、createBean()、doCreateBean()创建bean的流程,接着会通过反射创建出我们的bean实例对象,然后进行populateBean()属性填充,属性填充完成后,会执行bean的初始化,初始化bean过程主要执行Aware接口方法、执行初始化方法、回调BeanPostProcessor后置处理器的方法等。

  1. 第十二步,完成上下文的刷新工作,如清除一些缓存、发布容器刷新完成的事件等。
// AbstractApplicationContext.java

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 执行一些容器刷新前的准备工作,如设置容器启动时间、一些状态标志位等。
        // Prepare this context for refreshing.
        prepareRefresh();

        // 2. 创建容器对象,其实就是实例化DefaultListableBeanFactory对象,
        // 这一步包含了bean定义信息的解析,解析后的属性都封装到DefaultListableBeanFactory的成员属性中了,
        // 如我们常见的beanDefinitionMap、beanDefinitionNames;
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 3. 准备Bean工厂,实际上就是设置beanFactory的一些属性;
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // 4. Spring提供了postProcessBeanFactory()方法给我们取扩展,
            // 例如我们可以注册一些特殊的BeanPostProcessor后置处理器等操作;
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // 5. 执行BeanFactoryPostProcessor后置处理器的postProcessBeanFactory()增强方法,
            // 使用三个不同的集合分别存放实现了PriorityOrdered接口、实现了Ordered接口、普通的BeanFactoryPostProcessor,
            // 经过排序后,执行BeanFactoryProstProcessor的回调postProcessBeanFactory();
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册BeanPostProcessor后置处理器,
            // 注意,这里还不会执行BeanPostProcessor对应的增强方法;
            // 同样的,使用三个不同的集合分别存放实现了PriorityOrdered接口、实现了Ordered接口、普通的BeanPostProcessor,
            // 依次调用beanFactory.addBeanPostProcessor(postProcessor)方法往bean工厂中添加BeanPostProcessor;
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // 7. 为上下文初始化MessageSource,即国际化处理;
            // Initialize message source for this context.
            initMessageSource();

            // 8. 初始化事件广播器,即ApplicationEventMulticaster,为后面的事件发布-监听做准备;
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // 9. 提供了一个模版方法onRefresh(),留给子类初始化其他的bean;
            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // 10. 注册Listener监听器
            // Check for listener beans and register them.
            registerListeners();

            // 11. 实例化所有剩下的非懒加载的单例Bean,Bean的生命周期也是从这里开始的。
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // 12. 完成上下文的刷新工作,如清除一些缓存、发布容器刷新完成的事件等。
            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}