美文网首页Spring源码
IOC的初始化过程

IOC的初始化过程

作者: KingdomCoder | 来源:发表于2020-04-22 17:35 被阅读0次
    1.概述

    简单来说IOC容器的初始化过程是通过refresh()方法来启动的,这个方法表示IOC容器的正式启动。具体来说这个启动主要包含BeanDefinition的Resource定位、载入和注册三个过程。

    2.IOC启动流程说明
    • 第一个过程是Resource定位过程。 这个 Resource定位指的是BeanDefinition的资源定位(例如我们平时Spring项目中配置的各种xml配置统一抽象为Resource资源),它由ResourceLoader通过统一的Resource接口来完成,这个Resource对这种形式的BeanDefinition的使用提供了统一接口。
    • 第二个过程是BeanDefinition的载入过程。 载入过程是把用户定义好的Bean表示成IOC容器内部的数据结构即BeanDefinition。BeanDefinition实际上就是POJO对象在IOC容器中的抽象,通过对BeanDefinition定义的数据结构,使IOC容器能够方便的对POJO对象也就是Bean对象进行管理。
    • 第三个过程就是BeanDefinition的向IOC的注册过程。 这个过程主要是通过BeanDefinitionRegistry接口完成实现的。注册过程是把载入过程中解析得到的BeanDefinition向IOC容器进行注册。其实IOC内部就是将解析得到的BeanDefinition注入到一个HashMap中去,IOC容器就是通过这个HashMap持有这些BeanDefinition数据的。
    3.源代码解析

    FileSystemXmlApplicationContext为例,核心继承关系为:

    FileSystemXmlApplicationContext核心继承关系
    示例代码为:
    FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:bean.xml")
    

    当我们执行上面这行代码的时候一个IOC的资源定位、解析、注册过程就被完成,下面我们就分析一下上述代码的核心执行流程。

    /**
         * Create a new FileSystemXmlApplicationContext, loading the definitions
         * from the given XML file and automatically refreshing the context.
         * @param configLocation file path
         * @throws BeansException if context creation failed
         */
        public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
            this(new String[] {configLocation}, true, null);
        }
    

    我们选用的构造器为传入一个资源文件路径,实际调用的内部构造器为:

    /**
         * Create a new FileSystemXmlApplicationContext with the given parent,
         * loading the definitions from the given XML files.
         * @param configLocations array of file paths
         * @param refresh whether to automatically refresh the context,
         * loading all bean definitions and creating all singletons.
         * Alternatively, call refresh manually after further configuring the context.
         * @param parent the parent context
         * @throws BeansException if context creation failed
         * @see #refresh()
         */
        public FileSystemXmlApplicationContext(
                String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
                throws BeansException {
            // 父容器设置
            super(parent);
            // 设置资源访问路径
            setConfigLocations(configLocations);
            // 刷新启动容器
            if (refresh) {
                refresh();
            }
        }
    

    当我们执行refresh()方法的时候,我们的ApplicationContext高级上下文容器就已经创建好了,我们进入refresh()方法区查看具体执行的逻辑:

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // 刷新启动前的准备工作
            prepareRefresh();
    
            // Tell the subclass to refresh the internal bean factory.
            // 获取Beanfatory->资源的定位和解析就是在此方法中执行的
            //(1)AbstractApplicationContext#obtainFreshBeanFactory()
            //(2)AbstractApplicationContext#refreshBeanFactory()实际执行子类
            //(3)AbstractRefreshableApplicationContext#refreshBeanFactory()的方法
            创建DefaultListableBeanFactory并loadBeanDefinitions`
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // Prepare the bean factory for use in this context.
            // 配置BeanFactory标准Context特征,比如 classloader,后置处理等。
            prepareBeanFactory(beanFactory);
    
            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 允许添加BeanFactoryProcessor来修改beanFactory,子类覆盖方法做额外处理  
                postProcessBeanFactory(beanFactory);
    
                // Invoke factory processors registered as beans in the context.
                // 回调 上面收集到的所有的 BeanFactoryProcessor 了
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                // 注册bean的处理器
                registerBeanPostProcessors(beanFactory);
    
                // Initialize message source for this context.
                // 国际化相关的初始化
                initMessageSource();
    
                // Initialize event multicaster for this context.
                // 初始化应用事件的广播
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                // 留给子类Context实现一些特殊处理的模板方法(模板方法留给子类实现)
                onRefresh();
    
                // Check for listener beans and register them.
                // 注册监听器
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                // 单例实例化
                finishBeanFactoryInitialization(beanFactory);
    
                // 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();
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:IOC的初始化过程

        本文链接:https://www.haomeiwen.com/subject/czjwihtx.html