当前位置: 首页 > news >正文

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

文章目录

  • 什么是 SpringBoot 自动配置
  • Spring 加载 Bean
    • 问题描述
    • 原因分析
    • 解决方案
      • @ComponentScan
      • @Import
        • 1 . 导入类
        • 2 . 导入 ImportSelector 接口实现类
        • 问题

什么是 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 采用的也是这种方式
http://www.xdnf.cn/news/1243225.html

相关文章:

  • LeetCode 132:分割回文串 II
  • Linux开发利器:探秘开源,构建高效——基础开发工具指南(下)【make/Makefile】
  • 水面垃圾清扫船cad【6张】三维图+设计说明书
  • Jmeter进行性能并发测试
  • 【Java】使用FreeMarker来实现Word自定义导出
  • C++高频知识点(十四)
  • 京东商品详情API技术文档框架及Python实现方案
  • sqli-labs:Less-27a关卡详细解析
  • 《Python 实用项目与工具制作指南》· 2.3 导入
  • Bean的生命周期和循环依赖问题的解决
  • curl发送文件bodyParser无法获取请求体的问题分析
  • 嵌入式硬件中三极管推挽电路控制与实现
  • PPT自动化 python-pptx - 11 : 备注页 (Notes Slides)
  • (论文速读)Text-IF:基于语义文本引导的退化感知交互式图像融合方法
  • sqli-labs-master/Less-31~Less-40
  • openeuler离线安装软件
  • Hexo - 免费搭建个人博客07 - 添加右上角的“目录”
  • 先知模型或者说从容的模型
  • Linux—yum仓库及NFS网络共享服务
  • Java基础-斗地主游戏
  • opencv引入libavif
  • 从 0 到 1 开发图书管理系统:飞算 JavaAI 让技术落地更简单
  • Prometheus-3--Prometheus是怎么抓取Java应用,Redis中间件,服务器环境的指标的?
  • 【慕伏白】Android Studio 配置国内镜像源
  • 内联函数:提升效率的空间换时间艺术
  • FreeRTOS源码分析四:时钟中断处理响应流程
  • 深入浅出 RabbitMQ:工作队列实战(轮训策略VS公平策略)
  • 鸿蒙南向开发 编写一个简单子系统
  • 机器学习 入门——决策树分类
  • 并发编程常用工具类(下):CyclicBarrier 与 Phaser 的协同应用