SpringBoot自动配置

2023-11-18

目录

SpringBoot自动配置

SpringBoot自动配置-AutoConfiguration

  • 指基于引入的jar包 对SpringBoot应用进行自动配置
    (自动进行Bean的配置 省去了使用Spring框架时在xml中配置Bean这一步)

  • 为SpringBoot框架的开箱即用提供了基础支撑

配置类-ConfigurationClass

  • 广义的: 被注解@Component直接或间接修饰的某个类 即我们常说的Spring组件

    被@Component修饰的类本身作为Bean

  • 狭义的: 被注解@Configuration所修饰的某个类 又称@Configuration类

    被@Configuration修饰的类本身和其中被@Bean修饰的方法的返回值作为Bean

SpringBoot自动配置的例子

如自动配置redis

  1. 引入依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置redis服务器

    spring:
      redis:
        database: 0
        host: 127.0.0.1
        port: 6379
        password: 123456
    
    
  3. 直接使用RedisTemplate

    @Autowired
    private RedisTemplate redisTemplate;
    

整个过程中 我们没有通过任何操作在applicationContext中注册RedisTemplate 这个Bean

SpringBoot启动流程

从SpringApplication.run(…)开始:

  1. 创建一个ApplicationContext实例 即创建ioc容器

  2. 注册主类到ioc容器中(简单但重要的一步)

    被@SpringBootApplication所修饰的类
    一般为main方法所在的类
    这个类将作为遍历配置类的起点

  3. 递归加载并处理所有的配置类

    SpringBoot自动找到所有的配置类
    然后加载和处理他们

  4. 实例化所有的单例Bean

    实例化所有的单例Bean
    依赖注入和自动装配就属于其中的环节

  5. 如果是web应用 启动一个web服务器

步骤3-加载并处理所有的配置类

在这里插入图片描述

  1. SpringBoot首先处理朱磊的@ComponentScan注解

    扫描指定的package 得到一系列的配置类

    包括@Component修饰的 @Configuration修饰的类

    如果在这些扫描得到的配置类上存在@ComponentScan 则递归处理

    以此步骤加载所有的程序中定义的配置类

  2. 处理注解@Import

    根据Import注解的处理结果 可以得到一系列被导入的配置类

    如果此步骤中得到的配置类上依然存在@Import注解 也是通过递归处理的

  3. 处理被@Bean修饰的方法

  4. 处理@Import导入的ImportBeanDefinitionRegistrar

  5. 加入到一个全局的配置类集合中
    在这里插入图片描述

通过递归遍历 SpringBoot发现了所有的配置类

对配置类进行解析处理 并将得到的BeanDefinition注册到ioc容器中

@ComponentScan注解

  • 对指定的package进行扫描 找到其中符合条件的类

  • 默认是搜索被注解@Component修饰的配置类 (包括直接修饰的和间接修饰的)

  • 通过属性basePackages或basePackageClasses来指定要进行扫描的package

  • 如果未指定package 则默认扫描当前@ComponentScan所修饰的类所在的package

@Import注解

  • 提供了一种显示的 从其他地方加载配置类的方式 用于避免使用性能较差的组件扫描(Component Scan)

  • 支持导入:

    • 普通类(非后面所说两个接口的实现类)

    • 接口importSelector的实现类

    • 接口importBeanDefinitionRegistrar的实现类

import导入普通类例子

注意此处ConfigA没有被@Component直接或间接的修饰
在这里插入图片描述

在这里插入图片描述

导入ImportSelector接口的实现类例子

可以通过@import导入一个ImportSelector实现类

ImportSelector接口中的selectImports方法

他的返回值是一个字符串数组

数组中的每一个元素都代表一个将被导入的配置类的全限定名

利用这一特性 我们可以给ioc容器动态的导入多个配置类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

导入接口ImportBeanDefinitionRegistrar实现类例子

在ImportBeanDefinitionRegistrar的实现类中

可以手动向registry(可以理解为目标ioc容器)中注册多个Bean定义

从而实现个性化定制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结-SpringBoot加载配置类的方式

  • 使用注解@ComponentScan

  • 使用注解@Import

    • 导入普通类

    • 导入选择器ImportSelector

    • 导入注册器 ImportBeanDefinitionRegistrar

实现自动配置的方式

如果@ComponentScan实现

通过包扫描向ioc容器中注册第三方jar包中定义的Bean

需要记住每个第三方jar包中需要被扫描的包的名称

然后在程序中进行扫描包

性能较差 使用不便 不符合SpringBoot开箱即用的理念

如果使用@Import导入普通类实现

需要记住具体的类名

虽然性能相比包扫描ComponentScan好

但依然使用不便

如果使用@Import导入注册器ImportBeanDefinitionRegistrar实现

ImportBeanDefinitionRegistrar导入的不是Bean

而是BeanDefinition

是针对@Bean方法的补充

用于实现自动配置并不恰当

(不理解…)

如果使用@Import导入选择器ImportSelector

SpringBoot实现自动配置使用的方式

@SpringBootApplicaton被@EnableAutoConfiguration注解修饰

@EnableAutoConfiguration注解被@Import(AutoConfigurationImportSelector.class)修饰

SpringBoot通过@Import(AutoConfigurationImportSelector.class)来实现自动配置

@SpringBootApplication注解结构

在这里插入图片描述
@SpringBootApplication注解结构图

  • @SpringBootApplication修饰的类 会被@Configuration间接修饰 即"源配置类"

  • SpringBoot框架会对"源配置类"所在的package进行组件扫描(ComponentScan)

  • SpringBoot通过@Import(AutoConfigurationImportSelector.class)来实现自动配置

SpringBoot自动装配的原理

如何实现AutoConfigurationImportSelector

"开箱即用"即用户只需要引入jar包即可

不需要关心jar包中有哪些自动装配类

类名是什么 所在的包名是什么 都不需要用户关心

SpringBoot采用SpringFactories机制实现这一点

  • javaSPI机制的延申和扩展

  • SpringFactories是javaSPI设计思想的延申和扩展

  • SpringBoot基于它来实现的自动配置功能

SpringFactories机制

核心逻辑为:

从classpath中读取到所有jar包中的配置文件META-IF/spring.factories

然后根据指定的key从配置文件中解析出对应的value

AutoConfigurationImportSelector

在AutoConfigurationImportSelector的selectImports方法中:

  1. 通过SpringFactories机制加载配置文件

    通过ClassLoader去获取classpath中的配置文件META-INF/spring.factories

  2. 找出所有的自动配置类

    在所有的配置文件META-INF/spring.factories中

    筛选出以EnableAutoConfiguration.class为key的 符合条件的配置类
    (spring.factories内容格式为:“key=value1,value2,…valueN”)

  3. 根据@Conditional过滤掉不必要的自动装配类

    @Conditional 提供了配置过滤机制

    在特定条件满足时才会向ioc容器注册指定组件

    可以理解为一种特殊的if语句(待补充)

SpringFactories机制对比JavaSPI机制

  • 相同的:

    • 都要求第三方jar包提供配置文件

    • 都使用ClassLoader.getResource(…)读取配置文件

  • 不同的

    • 约定的配置文件路径不同

      • SpringFactories机制:
        META-IF/spring.factories

      • JavaSPI机制:
        META-IF/services/<Service接口的全限定名>

    • 配置文件内容不同

      • SpringFactories机制:
        内容格式为:“key=value1,value2,…valueN”

      • JavaSPI机制:
        内容格式是serviceProvider的类全限定名
        多个Provider类的话每个类名占据一行

    • loader类不同

      • SpringFactories机制:
        通过类SpringFactoriesLoader返回一个类名的集合
        可以根据需求对这些类名进行下一步处理

      • JavaSPI机制:
        返回一个ServiceProvider的对象实例集合

示意图

在这里插入图片描述

总结

SpringBoot实现bean自动配置

需要获知 在第三方jar包中 那些类是需要被配置的bean

只要能够获知这一点 就可以与配置程序中自定义bean相同的方式来处理这些类

获知这一点是使用了一种类似JavaSPI机制的方式:SpringFactories机制

SpringBoot在启动时 读取classpath下的所有spring.factories文件

从key为EnableAutoConfiguration.class的value中获取到所有需要进行自动配置的类的全限定名

至此 springBoot获取了实现自动配置需要的所有信息

此文章为https://www.bilibili.com/video/BV1NY411P7VX/?spm_id_from=333.788&vd_source=e974e5b422b5e93d638b7ac74272a918视频的学习笔记
感谢原内容作者码场安员外

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot自动配置 的相关文章

  • Java:如何从转义的 URL 获取文件?

    我收到了一个定位本地文件的 URL 事实上我收到的 URL 不在我的控制范围内 URL 按照 RFC2396 中的定义进行有效转义 如何将其转换为 Java File 对象 有趣的是 URL getFile 方法返回一个字符串 而不是文件
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • 在Spring中使用什么样的“EventBus”?内置、Reactor、Akka?

    我们将在几周后启动一个新的 Spring 4 应用程序 我们希望使用一些事件驱动的架构 今年 我到处读到有关 Reactor 的内容 在网上查找时 我偶然发现了 Akka 所以现在我们有3个选择 春天的ApplicationEvent ht
  • 如何使用 Java 处理 Selenium WebDriver 中的新窗口?

    这是我的代码 driver findElement By id ImageButton5 click Thread sleep 3000 String winHandleBefore driver getWindowHandle drive
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • 使用 AES SecretKey 的 Java KeyStore setEntry()

    我目前正在 Java 中开发一个密钥处理类 特别是使用 KeyStore 我正在尝试使用 AES 实例生成 SecretKey 然后使用 setEntry 方法将其放入 KeyStore 中 我已经包含了代码的相关部分 The KS Obj
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • 如何在selenium服务器上提供自定义功能?

    我知道可以通过某种方法获得一些硒功能 其中之一如下 driver getCapabilities getBrowserName 它返回浏览器名称的值 但如果它指的是一个可用的方法 如果我没有误解的话 这似乎与自定义功能有关 就像我的意思是
  • Jersey 客户端请求中未设置 Content-Length-Header

    我正在使用 Jersey Client 访问网络服务 如下所示 response r accept MediaType TEXT PLAIN TYPE header content length 0 post String class 其中
  • Struts 2 + Sitemesh 3 集成 - FreemarkerDecoratorServlet 中的 NPE

    我将 Struts 2 版本 2 3 14 3 与 Sitemesh 3 版本 3 0 alpha 2 一起使用 并且在某些情况下遇到 NullPointerException 首先 这是我的 web xml 中的 struts2 site
  • 测试弱引用

    在 Java 中测试弱引用的正确方法是什么 我最初的想法是执行以下操作 public class WeakReferenceTest public class Target private String value public Targe
  • Cucumber Java 与 Spring Boot 集成 - Spring @Autowired 抛出 NullPointer 异常

    我正在为 Spring boot 应用程序编写 cucumber java 单元测试来测试每个功能 当我与 Spring Boot 集成时 Autowired 类抛出 NullPointer 异常 Spring Boot应用程序类 Spri
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • Trie 数据结构 - Java [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 是否有任何库或文档 链接提供了在 java 中实现 Trie 数据结构的更多信息 任何帮助都会很棒 Thanks 你可以阅读Java特里树
  • ServletContainer 类未找到异常

    我无法再编译我的球衣项目 并且出现以下异常 GRAVE Servlet Project API threw load exception java lang ClassNotFoundException com sun jersey spi
  • 调整添加的绘制组件的大小和奇怪的摆动行为

    这个问题困扰了我好几天 我正在制作一个特殊的绘画程序 我制作了一个 JPanel 并添加了使用 Paint 方法绘制的自定义 jComponent 问题是 每当我调整窗口大小时 所有添加的组件都会 消失 或者只是不绘制 因此我最终会得到一个
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import
  • 如何在 JFreeChart 中设置多个系列的线条粗细?

    我创建了很多图表 在他们每个人中我都需要打电话 renderer setSeriesStroke i new BasicStroke 2 0f 对于每个系列 renderer is chart getXYPlot getRenderer 我

随机推荐