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的作业流程及参与的角色。

原文地址:https://www.cnblogs.com/xinde123/p/7644469.html