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

 更新时间:2021年06月04日 12:00:04   作者:梦里一明月  
今天带大家了解SpringBoot的相关知识,文中对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 是爆红的

aspectj相关的包是爆红的

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

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

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

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

在这里插入图片描述

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

六、总结

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

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

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

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

相关文章

  • Java之键盘输入语句Scanner解读

    Java之键盘输入语句Scanner解读

    这篇文章主要介绍了Java之键盘输入语句Scanner解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • JAVA集合框架专题

    JAVA集合框架专题

    这篇文章主要介绍了JAVA集合框架的相关知识,文中讲解非常细致,帮助大家更好的理解学习JAVA框架,感兴趣的朋友快来了解下
    2020-06-06
  • Java中的==使用方法详解

    Java中的==使用方法详解

    这篇文章主要介绍了Java中“==”的使用方法,,==可以使用在基本数据类型变量和引用数据类型变量中,equals()是方法,只能用于引用数据类型,需要的朋友可以参考下
    2022-09-09
  • Java经典排序算法之插入排序

    Java经典排序算法之插入排序

    这篇文章主要为大家详细介绍了Java经典排序算法之插入排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • Spring配置数据源流程与作用详解

    Spring配置数据源流程与作用详解

    这篇文章主要介绍了使用SpringBoot配置多数据源的经验分享,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Spring Cloud Hystrix 服务降级限流策略详解

    Spring Cloud Hystrix 服务降级限流策略详解

    这篇文章主要为大家介绍了Spring Cloud Hystrix 服务降级限流策略详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 详解Java Project项目打包成jar,并生成exe文件

    详解Java Project项目打包成jar,并生成exe文件

    本篇文章主要介绍了Java Project项目打包成jar,并生成exe文件,非常具有实用价值,有兴趣的可以了解一下。
    2017-01-01
  • Java 数据结构与算法系列精讲之时间复杂度与空间复杂度

    Java 数据结构与算法系列精讲之时间复杂度与空间复杂度

    对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间,这篇文章主要给大家介绍了关于Java时间复杂度、空间复杂度的相关资料,需要的朋友可以参考下
    2022-02-02
  • 详解Java的MyBatis框架中的事务处理

    详解Java的MyBatis框架中的事务处理

    利用MyBatis框架的配置管理比直接使用JDBC API编写事务控制要来得更加轻松,这里我们就来详解Java的MyBatis框架中的事务处理,尤其是和Spring框架集成后更加exciting
    2016-06-06
  • easyexcel读取excel合并单元格数据的操作代码

    easyexcel读取excel合并单元格数据的操作代码

    这篇文章主要介绍了easyexcel读取excel合并单元格数据的操作代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-05-05

最新评论