Spring IoC学习之ApplicationContext中refresh过程详解

下面是关于“Spring IoC学习之ApplicationContext中refresh过程详解”的完整攻略。

前言

在使用Spring框架时,我们经常会用到ApplicationContext容器,并在容器初始化时调用refresh()方法来启动容器。那么这个过程中都做了些什么呢?本文将详细解析ApplicationContext容器的refresh()过程,帮助读者更好的理解Spring框架中实例化、属性注入、AOP、事务管理等方面的知识点。

refresh()方法概述

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    ...

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 准备刷新容器
            prepareRefresh();

            // 准备Bean工厂
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 设置Bean工厂的类加载器、后置处理器、属性编辑器等
            prepareBeanFactory(beanFactory);

            try {
                // 支持子类覆盖的方法,用于加载Bean定义,装配Bean组件
                postProcessBeanFactory(beanFactory);

                // 实例化并注入非懒加载的单例Bean对象
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册Bean后置处理器,通常用于Bean初始化前后的扩展操作
                registerBeanPostProcessors(beanFactory);

                // 初始化剩余非懒加载的Bean对象
                initMessageSource();

                // 初始化资源查找器
                initApplicationEventMulticaster();

                // 预留用于子类的扩展点,留待子类自行实现
                onRefresh();

                // 注册应用中的事件监听器
                registerListeners();

                // 实例化并初始化剩余的单例Bean对象
                finishBeanFactoryInitialization(beanFactory);

                // 完成刷新过程,通常包括清除缓存和发布容器生命周期事件
                finishRefresh();
            }

            catch (BeansException | RuntimeException ex) {
                destroyBeans();

                cancelRefresh(ex);

                throw ex;
            }
        }
    }

    ...

}

从上面的源码中可以看到refresh()方法的整个执行过程,可以分为以下几个步骤:

  1. 准备刷新容器。
  2. 准备Bean工厂。
  3. 设置Bean工厂的类加载器、后置处理器、属性编辑器等。
  4. 支持子类覆盖的方法,用于加载Bean定义,装配Bean组件。
  5. 实例化并注入非懒加载的单例Bean对象。
  6. 注册Bean后置处理器,通常用于Bean初始化前后的扩展操作。
  7. 初始化剩余非懒加载的Bean对象。
  8. 初始化资源查找器。
  9. 预留用于子类的扩展点,留待子类自行实现。
  10. 注册应用中的事件监听器。
  11. 实例化并初始化剩余的单例Bean对象。
  12. 完成刷新过程,通常包括清除缓存和发布容器生命周期事件。

下面将逐一介绍每一个步骤。

准备刷新容器

protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    initPropertySources();

    this.environment.validateRequiredProperties();

    this.earlyApplicationEvents = new LinkedHashSet<>();

    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(
                this.applicationListeners);
    }
    else {
        this.earlyApplicationListeners.addAll(this.applicationListeners);
    }

    this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(this.beanFactory);
    this.applicationEventMulticaster.setErrorHandler(new ErrorHandler() {
        @Override
        public void handleError(Throwable throwable) {
            if (throwable instanceof BeanCreationException) {
                BeanCreationException bce = (BeanCreationException) throwable;
                if (logger.isErrorEnabled() && bce.getBeanName() != null) {
                    logger.error("Error creating bean with name '" + bce.getBeanName() + "'", bce);
                }
            }
        }
    });

    // 留待容器刷新监听器进行处理
    this.refreshListeners.clear();
    addApplicationListener(new SourceFilteringListener(this, new RefreshListener()));

    // 如果用户没有配置BeanNameGenerator,则默认使用AnnotationBeanDefinitionParser
    if (this.beanNameGenerator == null) {
        this.beanNameGenerator = new AnnotationBeanNameGenerator();
    }

    // 如果没有默认的`ClassLoader`使用当前线程的`ClassLoader`
    if (this.resourceLoader == null) {
        this.resourceLoader = this;
    }
}

在刷新容器前准备工作主要包括以下内容:

  1. 设置容器的启动时间、关闭状态和活跃状态。
  2. 初始化属性源,如从环境中获取属性配置文件。
  3. 校验需要的属性是否配置完整。
  4. 初始化早期的ApplicationEventApplicationListener
  5. 初始化应用事件的广播器。
  6. 注册容器刷新监听器,并将其添加到广播器中。
  7. 设置默认的BeanNameGeneratorClassLoader

准备Bean工厂

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

准备Bean工厂包括刷新Bean工厂和获取Bean工厂,具体流程如下:

  1. 刷新Bean工厂。在这一步中会销毁原有的Bean工厂,读取新的Bean定义并将其装配成一个可用的Bean组件。
  2. 获取Bean工厂,该方法返回的就是我们最终的Bean工厂实例。

设置Bean工厂

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 添加占位符,避免因Bean依赖注入出错而导致应用启动失败
    beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(beanFactory);
            }
            return bean;
        }
    });

    // 设置类装载器
    if (!(beanFactory instanceof DefaultListableBeanFactory)) {
        return;
    }
    DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
    dlbf.setAutowireCandidateResolver(new SimpleAutowireCandidateResolver(dlbf.getBeanClassLoader()));
    dlbf.setDependencyComparator(getDependencyComparator());
    Set<Object> seen = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
        postProcessor.postProcessBeanFactory(dlbf);
    }
    if (!getBeanNamesForTypeIncludingAncestors(BeanFactoryPostProcessor.class, true, false).containsAll(this.beanFactoryPostProcessorSet)) {
        LinkedList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new LinkedList<>();
        for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
            if (!this.beanFactoryPostProcessorSet.contains(postProcessor) && postProcessor instanceof PriorityOrdered) {
                nonOrderedPostProcessors.add(postProcessor);
            }
        }
        OrderComparator.sort(nonOrderedPostProcessors);
        this.beanFactoryPostProcessorList.addAll(nonOrderedPostProcessors);
    }
    for (BeanFactoryPostProcessor postProcessor : this.beanFactoryPostProcessorList) {
        postProcessor.postProcessBeanFactory(dlbf);
    }
    annoProcessor.setBeanFactory(beanFactory);
    for (Map.Entry<Class<?>, Object> entry : scopedBeans.entrySet()) {
        beanFactory.registerScope(entry.getKey().getName(), entry.getValue());
    }
    scopedBeans.clear();
    beanFactory.setTypeConverter(new StandardTypeConverter(beanFactory.getBeanClassLoader()));
    beanFactory.setTempClassLoader(null);

    // 注册自定义的属性编辑器
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    beanFactory.addPropertyEditorRegistrar(new EnvironmentEditorRegistrar(getEnvironment(), getConversionService()));
}

设置Bean工厂主要包括以下内容:

  1. 添加占位符,避免因Bean依赖注入出错而导致应用启动失败。
  2. 设置类装载器。
  3. 注册BeanFactoryPostProcessor对象,用于在Bean工厂的属性值初始化之前对其进行额外的处理。(在这一步中也会为BeanFactoryPostProcessor对象找到对应的Bean定义,并利用反射来调用postProcessBeanDefinitionRegistry()方法,以进一步扩展我们的容器。)
  4. 注册自定义的属性编辑器。

加载Bean定义

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 加载Bean定义
    // 数组的工厂名称已经预留出来了,为什么不用?直接调用这个方法。
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    getBeanDefinitionRegistrars().forEach(registrar -> registrar.registerBeanDefinitions(this));
    getBeanDefinitionReaderListeners().forEach(listener -> beanDefinitionReader.addBeanDefinitionListener(listener));
    loadBeanDefinitions(beanDefinitionReader);
}

在这一步中会创建一个XmlBeanDefinitionReader对象,并填充容器。具体流程如下:

  1. 创建XmlBeanDefinitionReader对象,并为其设置环境参数和资源装载器等一系列属性。
  2. 从配置文件中读取Bean定义,利用BeanDefinition实例来保存这些定义。
  3. 将读取到的Bean定义向容器中填充,并进行合适的处理,如注入依赖的其他Bean、对属性进行设置等操作。

实例化并注入非懒加载的单例Bean对象

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 执行BeanFactoryPostProcessor的回调。通常包括Bean定义修改、Bean删减等操作
    List<BeanFactoryPostProcessor> regularPostProcessors =
            this.beanFactoryPostProcessorList.stream().filter(beanFactoryPostProcessor -> !(beanFactoryPostProcessor instanceof PriorityOrdered)).collect(Collectors.toList());
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    for (BeanFactoryPostProcessor postProcessor : this.beanFactoryPostProcessorList) {
        if (postProcessor instanceof PriorityOrdered) {
            priorityOrderedPostProcessors.add(postProcessor);
        }
    }
    AnnotationAwareOrderComparator.sort(priorityOrderedPostProcessors);
    regularPostProcessors.addAll(priorityOrderedPostProcessors);
    for (BeanFactoryPostProcessor postProcessor : regularPostProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }

    // 执行BeanDefinitionRegistryPostProcessor的回调
    List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            currentRegistryProcessors.add((BeanDefinitionRegistryPostProcessor) postProcessor);
        }
    }
    List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new ArrayList<>();
    List<String> candidateNames = new ArrayList<>(beanFactory.getBeanDefinitionCount());
    candidateNames.addAll(Arrays.asList(beanFactory.getBeanDefinitionNames()));
    String[] processorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String procName : processorNames) {
        if (beanFactory.isTypeMatch(procName, PriorityOrdered.class)) {
            registryPostProcessors.add(beanFactory.getBean(procName, BeanDefinitionRegistryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(procName, Ordered.class)) {
            currentRegistryProcessors.add(beanFactory.getBean(procName, BeanDefinitionRegistryPostProcessor.class));
        }
        else {
            registryPostProcessors.add(beanFactory.getBean(procName, BeanDefinitionRegistryPostProcessor.class));
        }
    }
    AnnotationAwareOrderComparator.sort(registryPostProcessors);
    currentRegistryProcessors.addAll(registryPostProcessors);
    Set<BeanDefinitionRegistryPostProcessor> processedBeans = new HashSet<>();
    for (BeanDefinitionRegistryPostProcessor postProcessor : currentRegistryProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(beanFactory);
        processedBeans.add(postProcessor);
    }
    currentRegistryProcessors.clear();

    // 实例化BeanFactoryPostProcessor类型的Bean并回调
    List<BeanFactoryPostProcessor> beanFactoryPostProcessors =
            new ArrayList<>(beanFactory.getBeansOfType(BeanFactoryPostProcessor.class, true, false).values());
    AnnotationAwareOrderComparator.sort(beanFactoryPostProcessors);
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}

实例化并注入非懒加载的单例Bean对象主要包括以下内容:

  1. 执行BeanFactoryPostProcessor的回调。通常包括Bean定义修改、Bean删减等操作。
  2. 执行BeanDefinitionRegistryPostProcessor的回调。
  3. 实例化BeanFactoryPostProcessor类型的Bean并回调。

注册Bean后置处理器

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            this.priorityOrderedPostProcessors.add(pp);
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            this.orderedPostProcessors.add(pp);
        }
        else {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            this.nonOrderedPostProcessors.add(pp);
        }
    }
    List<BeanPostProcessor> orderedPostProcessorList =
            new ArrayList<>(this.priorityOrderedPostProcessors);
    // we must not include priorityOrderedPostProcessors here anymore
    orderedPostProcessorList.addAll(this.orderedPostProcessors);
    // guarantee order within merged processors, while keeping registration order for non-Ordered ones
    AnnotationAwareOrderComparator.sort(orderedPostProcessorList);
    for (BeanPostProcessor postProcessor : orderedPostProcessorList) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }
    for (BeanPostProcessor postProcessor : this.nonOrderedPostProcessors) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

注册Bean后置处理器主要包括以下内容:

  1. 获取在容器中所有实现了BeanPostProcessor接口的实例Bean
  2. 按照BeanPostProcessor子类的Order顺序对Bean后置处理器进行排序。
  3. 注册Bean后置处理器。

初始化剩余非懒加载的Bean对象

```
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parentMessageSource if no parent message source
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring IoC学习之ApplicationContext中refresh过程详解 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • vdpa原理和实现

    以下是关于“vdpa原理和实现”的完整攻略,包括定义、原理、实现、示例说明和注意事项。 定义 vDPA(Virtual Data Path Acceleration)是一种虚拟化网络设备的技术,它可以将物理网络设备的数据路径卸载到虚拟机中,从而提高虚拟机的网络性能。vDPA技术是由Linux Foundation的DPDK社区开发的。 原理 vDPA技术的原…

    other 2023年5月8日
    00
  • layui表格搜索功能

    layui表格搜索功能 在网站开发中,数据的展示与搜索是一个很常见的需求。而在前端框架中,layui 是一个广受欢迎的UI框架,也提供了便捷的表格组件。本文将介绍如何在 layui 表格中添加搜索功能。 基本思路 Layui 表格中没有原生的搜索功能,但提供了许多基础组件,可以根据实际需要实现搜索功能。基本的实现思路如下: 获取用户输入的搜索关键字。 遍历表…

    其他 2023年3月28日
    00
  • 详解AngularJS控制器的使用

    当然!下面是关于\”详解AngularJS控制器的使用\”的完整攻略,包含两个示例说明。 详解AngularJS控制器的使用 在AngularJS中,控制器(Controller)是用于处理视图和数据之间交互的组件。下面是使用控制器的步骤和示例说明: 定义控制器:在JavaScript文件中,使用controller函数来定义一个控制器。 示例代码: app…

    other 2023年8月20日
    00
  • Shell中的单中括号和双中括号的用法详解

    下面是 “Shell中的单中括号和双中括号的用法详解”的完整攻略。 单中括号和双中括号的基本区别 单中括号 [ ] 和双中括号 [[ ]] 在 Shell 中都是用于条件测试的,但两者有一些差别。下表列出了两者的差别: 特性 单中括号 [ ] 双中括号 [[ ]] 逻辑判断 使用标准的条件测试;无法进行高级判断;不支持&&或||运算符。 拥有…

    other 2023年6月28日
    00
  • Windows 批处理cmd/bat常用命令详解

    Windows 批处理cmd/bat常用命令详解 前言 Windows 批处理(cmd/bat)是一种可以在 Windows 系统下执行的脚本语言,可以用于自动化任务、批量处理等场景。本文将介绍一些常用的批处理命令。 常用命令 echo echo 命令用于在控制台输出文本或变量,并且可以通过重定向符号将输出结果写入文件。示例如下: @echo off ech…

    other 2023年6月26日
    00
  • githubdesktop下载及使用

    GitHub Desktop 下载及使用 简介 GitHub Desktop 是一款 GitHub 官方提供的桌面应用程序,它可以帮助用户更加方便地管理 Github 上的代码仓库,支持 Windows 和 macOS 两种操作系统,具有以下特点: 可以直接从 GitHub 上克隆或创建代码仓库 支持本地修改、提交和推送代码到远程代码仓库 支持多个账户登录管…

    其他 2023年3月28日
    00
  • 360安全卫士怎么使用右键菜单管理?360安全卫士使用右键菜单管理教程

    360安全卫士怎么使用右键菜单管理? 简介 360安全卫士是一款广泛使用的安全软件,它不仅提供了各种安全保护功能,还提供了右键菜单管理功能,方便用户快速地进行文件和文件夹的管理。在本文中,我们将为大家介绍如何使用360安全卫士的右键菜单管理功能。 操作步骤 打开360安全卫士软件,点击菜单栏上的“工具箱”选项卡,找到并点击“右键菜单管理”。 在弹出的右键菜单…

    other 2023年6月27日
    00
  • C++的四种类型转换

    下面就是详细讲解 C++ 的四种类型转换的完整攻略。 强制类型转换 强制类型转换是在需要明确指示编译器执行转换的场合下,将一种数据类型转换成另一种类型。 强制类型转换的基本语法如下: (type) value 其中,(type) 是需要转换的目标类型,value 是需要转换的变量或者表达式。 C++ 中提供了四种强制类型转换: 静态转换(static_cas…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部