解读SpringBoot为什么要用DeferredImportSelector

 更新时间:2025年03月12日 08:39:16   作者:冰糖心书房  
这篇文章主要介绍了SpringBoot为什么要用DeferredImportSelector的情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

DeferredImportSelector 是 Spring Framework 3.1 引入的 ImportSelector 接口的增强版本,主要用于延迟加载配置类,提升 Spring Boot 应用的启动速度。

它允许在所有配置类处理完毕后,再根据其他配置类的信息选择性地导入一些配置类。

为什么使用 DeferredImportSelector?

传统的 ImportSelector 会在配置类解析的早期阶段执行,这意味着在选择要导入的配置类时,它可能无法访问完整的配置信息,导致无法做出最佳选择。

DeferredImportSelector 解决了这个问题,它的执行会被延迟到所有常规配置类都被处理之后,此时它可以访问到所有配置类的信息,从而做出更明智的导入决策。

DeferredImportSelector 的工作原理

注册: 当 Spring 容器解析配置类时,如果发现一个类实现了 DeferredImportSelector 接口,它不会立即执行 selectImports() 方法,而是将该 DeferredImportSelector 的实例注册到一个 DeferredImportSelectorHandler 中。

延迟执行: 在所有配置类都处理完毕后,DeferredImportSelectorHandler 会负责执行所有注册的 DeferredImportSelector

分组和排序 (可选): DeferredImportSelector 可以实现 DeferredImportSelector.Group 接口,将多个 DeferredImportSelector 分组,并按组进行排序。 Spring Boot 允许对 DeferredImportSelector.Group 进行排序以控制执行顺序。

selectImports() 方法:selectImports() 方法中,DeferredImportSelector 可以访问到整个 Spring 容器的配置信息,例如:

  • 已经注册的 Bean 定义。
  • 已经加载的配置类。
  • 环境信息 (Environment)。

返回要导入的配置类: selectImports() 方法返回一个 String 数组,包含了要导入的配置类的全限定名。 Spring 容器会根据这些全限定名来导入相应的配置类,并注册 Bean。

DeferredImportSelector 的优势

  • 延迟加载: 避免过早加载不必要的配置类,提升启动速度。
  • 更智能的配置选择: 基于已加载的配置信息,做出更精确的配置选择。
  • 条件化配置: 实现更复杂的条件化配置逻辑。
  • 排序和分组: 控制 DeferredImportSelector 的执行顺序。

DeferredImportSelector 的劣势

  • 更复杂:ImportSelector 更复杂,需要理解延迟加载和分组排序的机制。
  • 调试难度增加: 由于是延迟执行,调试时可能需要更多步骤。

DeferredImportSelector 的使用场景

  • 自动配置: Spring Boot 的自动配置机制大量使用了 DeferredImportSelector。 例如, EnableAutoConfiguration 注解使用 AutoConfigurationImportSelector 来选择需要导入的自动配置类。
  • 条件化配置: 根据某个 Bean 是否存在,或者某个配置属性的值来选择是否导入某个配置类。
  • 模块化: 将应用分解为多个模块,根据已加载的模块信息来选择导入其他模块的配置。

DeferredImportSelector 的示例

import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyDeferredImportSelector implements DeferredImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 可以获取注解信息 importingClassMetadata
        // 可以访问 Spring 容器中的 Bean 定义

        // 根据条件选择导入不同的配置类
        if (conditionA()) {
            return new String[] { "com.example.config.ConfigA" };
        } else {
            return new String[] { "com.example.config.ConfigB" };
        }
    }

    private boolean conditionA() {
        // 实现条件逻辑
        return true; // 示例:始终返回 true
    }
}

示例:分组和排序

import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class MyDeferredImportSelector implements DeferredImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.MyConfig"};
    }

    @Override
    public Class<? extends Group> getImportGroup() {
        return MyGroup.class;
    }

    public static class MyGroup implements Group {

        private final List<Entry> entries = new ArrayList<>();

        @Override
        public void process(AnnotationMetadata metadata, DeferredImportSelector importSelector) {
            // 可以根据metadata和importSelector的信息来决定是否添加entry
            entries.add(new Entry(metadata, importSelector.selectImports(metadata)));
        }

        @Override
        public Iterable<Entry> selectImports() {
            // 返回需要导入的类的列表,这里可以对entries进行排序,控制导入的顺序
            return entries;
        }
    }
}

如何使用 DeferredImportSelector

  • 实现 DeferredImportSelector 接口: 创建一个类并实现 DeferredImportSelector 接口,并重写 selectImports() 方法。
  • 实现 getImportGroup() 方法 (可选): 如果需要分组和排序,则实现 getImportGroup() 并返回一个实现了 Group 接口的类。
  • 注册 DeferredImportSelector: 可以通过 @Import 注解,或者在 META-INF/spring.factories 文件中注册 DeferredImportSelector

Spring Boot 自动配置中的应用

Spring Boot 的自动配置机制利用 DeferredImportSelector 实现了延迟加载和条件化配置。

  • @EnableAutoConfiguration 注解: 这个注解触发了自动配置机制。
  • AutoConfigurationImportSelector: @EnableAutoConfiguration 最终会使用 AutoConfigurationImportSelector 这个 DeferredImportSelector
  • spring.factories 文件: AutoConfigurationImportSelectorMETA-INF/spring.factories 文件中读取 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键对应的自动配置类列表。
  • 条件化过滤: AutoConfigurationImportSelector 会根据 Spring 容器中的条件 (例如,是否存在某个 Bean,或者某个配置属性的值) 来过滤这些自动配置类,只选择符合条件的自动配置类进行导入。

总结

DeferredImportSelector 是 Spring Boot 中一个重要的特性,它允许延迟加载和条件化配置,从而提升应用的启动速度和灵活性。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringMVC整合,出现注解没有起作用的情况处理

    SpringMVC整合,出现注解没有起作用的情况处理

    这篇文章主要介绍了SpringMVC整合,出现注解没有起作用的情况及处理,具有很好的参考价值,希望对大家有所帮助。
    2023-05-05
  • Java字符串编码知识点详解介绍

    Java字符串编码知识点详解介绍

    在本篇内容了小编给大家详细分析了关于Java字符串编码的知识点并对实例做了分析,有兴趣的朋友们跟着学习下。
    2022-11-11
  • java实现图片无损任意角度旋转

    java实现图片无损任意角度旋转

    这篇文章主要为大家详细介绍了java实现图片无损任意角度旋转,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • Java synchronized与CAS使用方式详解

    Java synchronized与CAS使用方式详解

    提到Java的知识点一定会有多线程,JDK版本不断的更迭很多新的概念和方法也都响应提出,但是多线程和线程安全一直是一个重要的关注点。比如说我们一入门就学习的synchronized怎么个实现和原理,还有总是被提到的CAS是啥,他和synchronized关系是啥?请往下看
    2023-01-01
  • Spring Boot 搭建 ELK正确看日志的配置流程

    Spring Boot 搭建 ELK正确看日志的配置流程

    这篇文章主要介绍了Spring Boot 搭建 ELK正确看日志的配置流程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • RestTemplate实现发送带headers的GET请求

    RestTemplate实现发送带headers的GET请求

    这篇文章主要介绍了RestTemplate实现发送带headers的GET请求,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Springboot内嵌tomcat应用原理深入分析

    Springboot内嵌tomcat应用原理深入分析

    懂得SpringBoot的童鞋应该很清楚,不管应用程序是属于何种类型,都是一个Main方法走遍天下,对于web应用,只需要引入spring-boot-starter-web中这个依赖,应用程序就好像直接给我们来了个tomcat一样,对于嵌入式Tomcat,其实也非常简单,就是调用Tomcat提供的外部类
    2022-09-09
  • java调用shell命令并获取执行结果的示例

    java调用shell命令并获取执行结果的示例

    今天小编就为大家分享一篇java调用shell命令并获取执行结果的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • Java实现学生成绩管理系统

    Java实现学生成绩管理系统

    这篇文章主要为大家详细介绍了Java实现学生成绩管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • 详解Java执行groovy脚本的两种方式

    详解Java执行groovy脚本的两种方式

    这篇文章主要介绍了Java执行groovy脚本的两种方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论