【Spring】SpringBoot 自动配置,@ComponentScan、@Import、ImportSelector接口

发布于:2025-08-05 ⋅ 阅读:(15) ⋅ 点赞:(0)

什么是 SpringBoot 自动配置

SpringBoot 的自动配置就是当 Spring 容器启动之后,一些配置类,bean 对象就自动存入到了 IoC 容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作

SpringBoot 自动配置,就是指 SpringBoot 是如何将依赖 jar 包中的配置以及 Bean 加载到 Spring IoC 容器中的

我们学习主要分以下两个方面:

  1. Spring 是如何把对象加载到 SpringIoC 容器中的
  2. SpringBoot 是如何实现的

Spring 加载 Bean

问题描述

需求:使用 Spring 管理第三方的 jar 包的配置

  • 引入第三方的包,其实就是在该项目下,引入第三方的代码,我们采用在该项目下创建不同的目录来模拟第三方的代码引入

数据准备

  1. 创建项目 spring-autoconfig,当前项目目录为:com.example.demo
  2. 模拟第三方代码文件在 com.bite.autoconfig 目录下image.png|251

第三方文件代码:

public class BiteConfig {  
    public void study() {  
        System.out.println("start study...");  
    }  
}
  1. 获取 BiteConfig 这个 Bean

写测试代码

@SpringBootTest  
class ApplicationTests {  
    @Autowired  
    private ApplicationContext applicationContext;  
    @Test  
    void contextLoads() {  
        BiteConfig biteConfig = applicationContext.getBean(BiteConfig.class, "biteConfig");  
        System.out.println(biteConfig);  
    }  
}
  1. 运行程序
    image.png
  • 观察日志:No qualifying bean of type 'com.bite.autoconfig.BiteConfig' available
  • 没有 com.bite.autoconfig.BiteConfig 这个类型的 Bean

原因分析

Spring 通过五大注解和 @Bean 注解可以帮助我们把 Bean 加载到 SpringIoC 容器中,以上有个前提就是这些注解类需要和 SpringBoot 启动类在同一个目录下(@SpringBootApplication 标注的类就是 SpringBoot 的启动类)

  • 启动类所在目录为:com.example.deml,而 BiteConfig 这个类在 com.bite.autoconfig 下,所以 SpringBoot 没有扫描到

解决方案

我们需要指定路径或者引入的文件,告诉 spring,让 Spring 进行扫描到

常见的解决方案有两种:

  1. @ComponentScan 组件扫描
  2. Import 导入(使用 @Import 导入的类会被 Spring 加载到 IoC 容器中)

我们通过代码来看如何解决

@ComponentScan

通过 @ComponentScan 注解,指定 Spring 扫描路径

@ComponentScan("com.bite.autoconfig")  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}
  • 可以指定扫描多个包 @ComponentScan({"com.bite.autoconfig","com.example.demo"})

运行程序:image.png|403

可以看到,这次 biteConfigBean 获取到了

  • Spring 是否使用了这种方式呢?
  • 非常明显,没有(因为我们引入第三方框架时,没有加扫描路径,如 mybatis
  • 如果 SpringBoot 采用这种方式,当我们引入大量的第三方依赖,比如 MyBatisjackson 等时,就需要在启动类上配置不同依赖需要扫描的包
  • 这种方式会非常繁琐

@Import

@Import 导入主要有以下几种形式

  1. 导入类
  2. 导入 ImportSelector 接口实现类

1 . 导入类
@Import(BiteConfig.class)  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}
  • 运行程序image.png
  • 可以看到,这种方式也可以告诉 Spring 加载 biteConfig

问题:如果又多了一些配置项呢?

@Component  
public class BiteConfig2 {  
    public void study2() {  
        System.out.println("start study2...");  
    }  
}

我们可以采用导入多个类

@Import({BiteConfig.class, BiteConfig2.class})  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}

很明显,这种方式也很繁琐,所以,SpringBoot 依然没有采用

2 . 导入 ImportSelector 接口实现类

ImportSelector 接口实现类

public class MyImportSelector implements ImportSelector {  
    @Override  
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {  
        // 需要导入的全限定类名  
        return new String[]{"com.bite.autoconfig.BiteConfig", "com.bite.autoconfig.BiteConfig2"};  
    }  
}

启动类:

@Import(MyImportSelector.class)  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}

运行程序:image.png|472

  • 可以看到,我们采用这种方式也可以导入第三方依赖提供的 Bean

问题

问题
但是他们都有一个明显的问题,就是使用者需要知道第三方依赖中有哪些 Bean 对象或配置类。如果漏掉了其中一些 Bean,就可能导致我们的项目出现大事故

依赖中有哪些 Bean,使用时需要配置哪些 Bean,第三方依赖最清楚,那能否由典发那个依赖来做这件事呢?

  • 比较常见的方案就是第三方依赖给我们提供一个注解,这个注解一般都以 @EnableXxxx 开头,注解中封装的就是 @Import 注解

  1. 第三方依赖提供注解
import org.springframework.context.annotation.Import;  
  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE)  
@Import(MyImportSelector.class)  
public @interface EnableBiteConfig {  
}

注解中封装 @Import 注解,导入 MyImportSelector.class

  1. 在启动类上使用第三方提供的注解
@EnableBiteConfig  
@SpringBootApplication  
public class Application {  
  
    public static void main(String[] args) {  
        SpringApplication.run(Application.class, args);  
    }  
  
}

运行程序:image.png

  • 可以看到,这种方式也可以导入第三方依赖提供的 Bean
  • 并且这种方式更优雅一点,SpringBoot 采用的也是这种方式

网站公告

今日签到

点亮在社区的每一天
去签到