zoukankan      html  css  js  c++  java
  • spring 内部工作机制(一)

    Spring内部机制的内容较多,所以打算多分几个阶段来写。

    本章仅探索Spring容器启动做了哪些事;

    前言:

    都说Spring容器就像一台构造精妙的机器,此话一点不假,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式工作。

    如果我们将Spring容器比喻为一辆汽车,可以将BeanFactory看成汽车的发动机,而ApplicationContext则是整辆汽车,它不但包括发动机,还包括离合器,变速器及底盘,车身,电器设备等其他组件,在ApplicationContext内,各个组件按部就班地完成汽车的各项功能。

    正文:

    Spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh( )方法定义了Spring容器在加载配置文件后的各项处理过程,非常清晰。

    我们来看一下这个方法内部定义了哪些执行逻辑。

    @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // ① 初始化BeanFactory
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
    
                    // ② 调用工厂后处理器
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // ③ 注册Bean后处理器
                    registerBeanPostProcessors(beanFactory);
    
                    // ④ 初始化消息源
                    initMessageSource();
    
                    // ⑤ 初始化应用上下文事件广播器
                    initApplicationEventMulticaster();
    
                    // ⑥ 初始化其他特殊的Bean,由具体子类实现
                    onRefresh();
    
                    // ⑦ 注册事件监听器
                    registerListeners();
    
                    // ⑧ 初始化所有单实例的Bean,使用懒加载模式的Bean除外
                    finishBeanFactoryInitialization(beanFactory);
    
                    // ⑨ 完成刷新并发布容器刷新事件
                    finishRefresh();
                }
    
                catch (BeansException ex) {
                  //
                }
    
                finally {
                    // Reset common introspection caches in Spring's core, since we
                    // might not ever need metadata for singleton beans anymore...
                    resetCommonCaches();
                }
            }
        }

    共九种主要的处理操作。下面再详细说说这些操作。

    (1) 初始化BeanFactory: 根据配置文件实例化BeanFactory,在obtainFreshBeanFactory()方法中,首先调用refreshBeanFactory()方法刷新BeanFactory,然后调用getBeanFactory()方法获取BeanFactory,

    这两个方法都是由具体子类实现的,在这一步里,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还未初始化。

    附上obtainFreshBeanFactory()方法的源码如下:

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (logger.isDebugEnabled()) {
                logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
            }
            return beanFactory;
        }

    (2) 调用工厂后处理器: 根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanFactoryPostProcessor接口的Bean,并调用其postProcessBeanFactory()接口方法。也附上部分源码吧。

    if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
                List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                        new LinkedList<BeanDefinitionRegistryPostProcessor>();
    
                for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                        BeanDefinitionRegistryPostProcessor registryPostProcessor =
                                (BeanDefinitionRegistryPostProcessor) postProcessor;
                        registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                        registryPostProcessors.add(registryPostProcessor);
                    }
                    else {
                        regularPostProcessors.add(postProcessor);
                    }
                }

    (3) 注册Bean后处理器: 根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将它们注册到容器Bean后处理器的注册表中。

    (4) 初始化消息源: 初始化容器的国际化消息资源。想必这个比较好理解。

    (5) 初始化应用上下文事件广播器。

    (6) 初始化其他特殊的Bean: 这是一个钩子方法,子类可以借助这个方法执行一些特殊的操作,如AbstractRefreshableWebApplicationContext就使用该方法执行初始化ThemeSource的操作。

    (7) 注册事件监听器。

    (8) 初始化所有单实例的Bean,使用懒加载模式的Bean除外:初始化Bean后,将它们放入Spring容器的缓存池中。(加一句:如果这个有懒加载标志的单实例Bean被一个非懒加载的单实例Bean引用时,那么懒加载失效)

    (9) 发布上下文刷新事件: 创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中。(关于事件的内容在下面的章节会有详解)

     

    下一章节讲Spring容器从加载配置文件到创建出一个完整Bean的作业流程及参与的角色。

  • 相关阅读:
    [Chapter 3 Process]Practice 3.4 Describe what happens when a context switch occurs if the new context is already loaded into one of the register sets.
    [Chapter 3 Process]Practice 3.3 Discuss three major complications that concurrent processing adds to an operating system.
    爬取:中国大学排名
    基础统计学--复习
    pandas之数据结构
    numpy之初探排序和集合运算
    numpy之统计函数和布尔数组方法
    numpy之meshgrid和where
    numpy之通用函数ufunc
    numpy之转置(transpose)和轴对换
  • 原文地址:https://www.cnblogs.com/xinde123/p/7644469.html
Copyright © 2011-2022 走看看