java进阶之了解SpringBoot的配置原理

一、Spring Boot的特点

首先我们要知道 Spring Boot 在底层已经为我们添加好了很多依赖。比如我们常用的Tomcat,Spring,SpringMVC这些,甚至连mysql数据库的依赖也为我们添加好了

不过 SpringBoot 2.5.0 使用的mysql依赖版本是8.0.25的,如果还在使用 mysql 5 版本的小伙伴们就需要在项目的 pom.xml 文件中再次指定自己所用的依赖版本号。(因为 maven 在引入依赖时采取就近原则,你如果指定了依赖版本号的话,它会加载离它近的,而不会去加载远的)

例如,我要修改 mysql 依赖的版本为5.1.43

//在当前项目里面重写配置
    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>

二、了解容器的功能

添加组件

@Configuration、@Bean注解

首先,这个注解是写在类上面的,告诉 spring boot 这是一个配置类,等同于 以前的配置文件

配置类里面使用@Bean标注在方法上给容器注册组件,默认情况下是单例的。以方法名就是组件的 id 。返回类型就是组件类型。返回的值,就是组件在容器中的实例

为什么他会是单例的呢? 原因是在@Configuration注解的源码中,还定义了一个属性 proxyBeanMethods ,默认值是 true。

当然我们也可以修改他的值为false,这样他就会创建多个对象了。

举个例子:

我现在在配置类里面定义了一个组件,他会返回一个 User 对象,当proxyBeanMethods = true 时,无论调用多少次 user01() 方法,在容器中都只会存在一个实例对象,但我现在把它改为 false ,来测试一下他到底是不是能创建多个实例了。

在主方法中进行测试:

User user=config.user01();
    User user1=config.user01();
    System.out.println(user==user1);

最后输出的结果是

false

这就说明现在创建了两个对象了,在容器中useruser1并不是指向同一块内存地址

那我们什么时候可以把它改成 false 来使用呢? 这就要设计到两种编写Spring Boot的方式了

  • 一种是FULL模式 全模式(单例)
  • 另一种是Lite模式 轻量级模式(非单例)

如果有组件依赖必须使用Full模式(默认)。其他默认是否Lite模式

Import注解

加入 IOC 容器的方式有很多种,上面的@Bean是一种,这里提到的@Import也是用来注册组件的,@Import注解可以用于导入第三方包 (当然@Bean也可以)

它是写在类上面的,

它所创建的组件 id 默认是类的全限定名称

具体用法参考:b站Spring注解驱动教程

Conditional注解

条件装配:满足Conditional指定的条件,则进行组件注入

@Conditional注解下面还有许多的子注解

因为它的子注解实在太多了,下面我们具体实现一个例子来说明一下它的功能

先在 User 类中再加入一个 Pet 属性

现在我希望容器在没有 Pet 的情况下,我也不要 User 对象

要实现这个需求,可以这样做,在 User 组件前面添加@ConditionalOnBean注解,并指定条件为 Pet 组件的 id 来进行限制

执行测试方法

运行结果:

容器中是否有tomcat:false
容器中是否有user:false

这样就对组件 User 的注册加以限制了

也可以把@ConditionalOnBean(name="tom")注解加在配置类上面,当容器中有 tom 组件时,这个类中的其他组件才会生效,否则不生效

三、原配置文件的引入

如果你原有的项目还是使用 beans.xml 等配置文件的方式来注册组件的话,SpringBoot 是肯定无法自动配置的,那怎么样才能让SpringBoot用我这个配置文件去注册组件呢?

@ImportResource注解

使用@ImportResource注解可以引入以前那种 xml 配置文件的方式写的组件

使用方法:直接加在现在的配置类上面,例如:

@ImportResource("classpath:beans.xml")

配置绑定

配置绑定是什么意思呢?其实就是使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用

具体做法:使用@ConfigurationProperties注解

这个注解是加在你需要从 properties 属性配置文件中要导入的属性的类上面。

比如:我现在写了一个 Car 类,然后在 properties 文件中写好了它的属性


( 注意:properties 文件中的所有属性均要小写,驼峰命名法也不行,可以用 - 或 _ 来代替 )

我们想要将配置文件中定义好的属性绑定到实例对象上的话,就可以在 Car 这个类上面加上@ConfigurationProperties(prefix = "mycar")prefix 代表前缀的意思。

单加上这一个注解还不行,因为此时容器中还没有这个对象,可以采用两种方式来把 Car 这个对象加入容器中:

1.使用@Component注解

2.使用@EnableConfigurationProperties注解

@Component+@ConfigurationProperties

@ConfigurationProperties注解上方加上@Component注解,即可将 Car 加入到容器中

测试方法:

运行,访问 “/car” 查看结果

@EnableConfigurationProperties+@ConfigurationProperties

使用@EnableConfigurationProperties注解则需要在配置类上面添加,而不是 Car 上面

这个注解的作用就是

1.开启Car的属性配置功能

2.把这个Car这个组件自动注册到容器中

再次运行程序,可以得到相同的结果

四、自动配置原理

说完上面这些,我们来看一下,Spring Boot是如何实现自动装配的

引导加载自动配置类

我们先点进@SpringBootApplication的源码中去,发现它其实是3个注解的合成注解:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

@SpringBootConfiguration

其中,@SpringBootConfiguration的源码底层使用了@Configuration注解,说明它其实也是一个配置类,只不过它相当于是一个主配置。

@ComponentScan

根据我们之前的学习,这个注解其实就是一个组件扫描器的作用,是Spring的注解

@EnableAutoConfiguration(核心)

最关键最核心的注解就是这个,@EnableAutoConfiguration

@AutoConfigurationPackage

我们点进它的源码里面去,发现它底层调用了一个叫@AutoConfigurationPackage的注解,翻译过来就是自动配置包,它指定了默认的包规则

再继续查看它的底层源码,发现它导入了一个叫Register的组件

点进去,给它打上一个断点,来看一下到底是如何运作的

代码现在在这里停住了,让我们来看一下这一行代码里面,发现它能够找到我们所在的包名,由此我们也就能知道为什么 Spring Boot 能够将指定的一个包下的所有组件导入进来了,

@Import({AutoConfigurationImportSelector.class})

@EnableAutoConfiguration注解下还有一个注解,它是干什么的呢?让我们看一下源码就知道了

AutoConfigurationImportSelector类下面我们找到了一个方法getAutoConfigurationEntry(annotationMetadata),它是用来给容器中批量导入一些组件的

给他打一个断点,看看到底加入了些什么组件进容器里

说明这 131 个对象都是要加入到容器中的,并且都存储在了一个List集合当中 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes)

为什么会是131个呢? 其实是Spring Boot 里面写死了,一启动就要给容器中加载的所有配置类

打开spring-boot-autoconfigure-2.5.0.RELEASE.jar下META-INF/spring.factories位置的文件,让我们来看一下源码是怎么写的

这里写了一大堆 xxxxAutoConfiguration 的配置类,从26行开始,到156行结束,刚好是 131 个。


虽然我们 131 个场景的所有自动配置启动的时候默认全部加载,但并不是都会生效的,比如 AOP 的部分功能就需要你导入 aspectj 相关的包才能生效。它是按照条件装配规则(@Conditional),最终会按需配置。

如图, aspectj 是爆红的

除了AOP之外,还有一些类也是没有生效的(比如CacheAutoConfiguration),这里就不再赘述了,感兴趣的同学可以去看源码了解一下。

五、修改默认配置(约定大于配置)

SpringBoot 默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

以 SpringMVC 中的文件上传解析器为例,他在容器中的默认名字是multipartResolver,但是我们写代码的时候可能不知道底层源码里面给他的默认名字是这个,我们给他起了另外一个名字,这个时候 SpringBoot 就会去容器中找到你所配置的那个组件,并且返回那个组件,也就是下面这段代码:

这是为了防止有些用户配置的文件上传解析器不符合规范。

六、总结

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置
  • 用户直接自己@Bean替换底层的组件
  • 用户去看这个组件是获取的配置文件什么值就去修改。

整个的流程:xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties

所以,当我们需要修改组件的配置的时候,只需要在application.properties里面进行配置即可

到此这篇关于java进阶之了解SpringBoot的配置原理的文章就介绍到这了,更多相关SpringBoot的配置原理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot静态资源配置原理(源码分析)

    前言: 我们都知道,SpringBoot启动会默认加载很多xxxAutoConfiguration类(自动配置类) 其中SpringMVC的大都数功能都集中在WebMvcAutoConfiguration类中,根据条件ConditionalOnxxx注册类对象:WebMvcAutoConfiguration满足以下ConditionalOnxxx条件,类是生效的,并把其对象注册到容器中. 那WebMvcAutoConfiguration生效给容器中配置了什么呢? WebMvcAutoConfig

  • 浅析SpringBoot自动化配置原理实现

    绪论 什么是SpringBoot? Spring Boot 是所有基于 Spring 开发的项目的起点.Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件.简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适). SpringBoot四个主要特性 SpringBoot Starter:他将常用的依赖分组进行了整

  • 浅谈springboot自动配置原理

    从main函数说起 一切的开始要从SpringbootApplication注解说起. @SpringBootApplication public class MyBootApplication { public static void main(String[] args) { SpringApplication.run(MyBootApplication.class); } } @SpringBootConfiguration @EnableAutoConfiguration @Compon

  • springboot自动配置原理解析

    前言 小伙伴们都知道,现在市面上最流行的web开发框架就是springboot了,在springboot开始流行之前,我们都用的是strust2或者是springmvc框架来开发web应用,但是这两个框架都有一个特点就是配置非常的繁琐,要写一大堆的配置文件,spring在支持了注解开发之后稍微有些改观但有的时候还是会觉得比较麻烦,这个时候springboot就体现出了它的优势,springboot只需要一个properties或者yml文件就可以简化springmvc中在xml中需要配置的一大堆

  • SpringBoot自动配置原理,你真的懂吗?(简单易懂)

    概述 上面博文(SpringBoot简介与快速搭建)我们简单的介绍了什么是SpringBoot,以及如何使用SpringBoot,但是我们对于SpringBoot的基本原理并没有介绍,这篇博文我们重点介绍SpringBoot是如何实现的自动配置. 依赖管理 在我们的pom文件中最核心的依赖就一个: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-star

  • java进阶之了解SpringBoot的配置原理

    一.Spring Boot的特点 首先我们要知道 Spring Boot 在底层已经为我们添加好了很多依赖.比如我们常用的Tomcat,Spring,SpringMVC这些,甚至连mysql数据库的依赖也为我们添加好了 不过 SpringBoot 2.5.0 使用的mysql依赖版本是8.0.25的,如果还在使用 mysql 5 版本的小伙伴们就需要在项目的 pom.xml 文件中再次指定自己所用的依赖版本号.(因为 maven 在引入依赖时采取就近原则,你如果指定了依赖版本号的话,它会加载离它

  • Java SpringBoot自动配置原理详情

    目录 SpringBoot的底层注解 配置绑定 自动配置原理入门 SpringBoot的底层注解 首先了解一些SpringBoot的底层注解,是如何完成相关的功能的 @Configuration 告诉SpringBoot被标注的类是一个配置类,以前Spring xxx.xml能配置的内容,它都可以做,spring中的Bean组件默认是单实例的 #############################Configuration使用示例###############################

  • springboot自动配置原理以及spring.factories文件的作用详解

    目录 一.springboot 自动配置原理 二.spring.factories文件的作用 spring.factories 的妙用 什么是 SPI 机制? Spring Boot 中的 SPI 机制 Spring Factories 实现原理是什么? Spring Factories 在 Spring Boot 中的应用 一.springboot 自动配置原理 先说说我们自己的应用程序中Bean加入容器的办法: package com.ynunicom.dc.dingdingcontract

  • SpringBoot自动配置原理详解

    目录 阅读收获 一.SpringBoot是什么 二.SpringBoot的特点 三.启动类 3.1 @SpringBootApplication 四.@EnableAutoConfiguration 4.1 @AutoConfigurationPackage 4.2  @Import({AutoConfigurationImportSelector.class}) 五.流程总结图 六.常用的Conditional注解 七.@Import支持导入的三种方式 阅读收获 理解SpringBoot自动配

  • SpringBoot 自动配置原理及源码解析

    初始化一个Springboot项目,在主启动类会有这么一个注解:@SpringBootApplication,自动装配的秘密全在主启动类这个注解里面了 点进去一层会发现有三个子注解组成,分别是 @SpringBootConfiguration.@ComponentScan和@EnableAutoConfiguration 接下来分别解释这三个注解在整个自动装配过程中的作用 1.@SpringBootConfiguration 点进去发现它是@Configure,代表当前是一个配置类,意思就是当前

  • 深入浅析SpringBoot自动配置原理

    SpringBoot2.3.1版本源码 一.SpringBoot启动的时候加载主配置类,通过@EnableAutoConfiguration注解开启了自动配置功能 . 二.@EnableAutoConfiguration作用: 1. 点击该注解进入可以发现,它利用AutoConfigurationImportSelector.class 选择器给SpringBoot导入一些组件.导入哪些组件呢?可以点击选择器进入查看selectImports()方法的内容,该方法最终会返回一个configurati

  • SpringBoot自动配置原理分析

    目录 前言 一.启动类 1.1.@SpringBootConfiguration 1.2.@EnableAutoConfiguration 1.3.@ComponentScan 1.4.探究方向 二.@SpringBootConfiguration 三.@EnableAutoConfiguration 3.1.@AutoConfigurationPackage 3.2.@Import(AutoConfigurationImportSelector.class) 3.2.1.getCandidat

随机推荐