SpringBoot2自动装配原理解析

 更新时间:2022年03月16日 10:43:40   作者:小超和你  
这篇文章主要介绍了SpringBoot2自动装配原理解析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

1、SpringBoot特点

1.1 依赖管理

父项目做依赖管理

springboot项目的父项目  
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
</parent>
 
spring-boot-starter-parent的父项目
 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.4.RELEASE</version>
  </parent>

父项目整合了所有开发中常用的依赖的版本号,称为自动版本仲裁机制。

注意:这不是说无需导入依赖了,而是指在导入依赖的时候,会自动仲裁(匹配)版本号,相当于模具的功能。

开发导入starter场景启动器

场景启动器的功能是:springboot已经帮我们整合了所有应用场景常规的依赖,只要依赖中写入某场景启动器,之下的所有依赖也都一一导入了。

  • 官方整合的场景启动器一般是:spring-boot-starter-*。
  • 只要引入starter,这个场景的所有常规需要的依赖都会自动引入。
  • SpringBoot所有支持的场景都在:https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter 这个地址里。
  • 第三方提供的简化开发的场景启动器一般是:*-spring-boot-starter
  • 所有场景启动器都有一个最底层的依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.3.4.RELEASE</version>
  <scope>compile</scope>
</dependency>

自动版本仲裁机制

意味着无需关注版本号,即导即用。

注意:

引入父项目中已经整合过的依赖,都可以不写版本号。

但引入没有版本仲裁的jar,需要写版本号。

如果对整合过的依赖的版本号不满意,可以修改默认的版本号,方法如下:

1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置,如:
    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>

1.2 自动配置

springboot已经配置好了那些繁文缛节的配置文件,不用我们额外的配置

比如:

1、Tomcat

2、SpringMVC(引入了全套组件、常用的功能)DispathcherServlet等

3、Web常见功能:字节编码,内部视图解析器

4、默认的扫描包结构

  • 之前我们在方法上加注释,需要在配置文件中扫描包名等,现在已经不需要了。
  • 主程序Application所在包及其子包里面的组件都会被默认扫描进来
  • 如果想要改变扫描路径,可以在主程序上的springboot声明注解中设置scanBasePackages属性
@SpringBootApplication(scanBasePackages="com.atguigu")
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}

5、各种配置拥有默认值

如果需要更改默认值,可以在resource文件下创建application.properties,修改其中的默认值

默认配置的原理:

  • 默认配置最终都是映射到某个类上,如:MultipartProperties
  • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
  • 引入了哪些场景这个场景的自动配置才会开启
  • SpringBoot所有的自动配置功能都在spring-boot-autoconfigure包里面

2、容器功能

2.1 组件添加

1、@Configuration

/**
 *  1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
 *  2、配置类本身也是组件
 *  3、proxyBeanMethods = true 默认是true 表示代理bean的方法 (动态代理)
 *    Full模式(proxyBeanMethods = true)
 *    Lite模式(proxyBeanMethods = false)
 *    组件依赖
 */
@Configuration(proxyBeanMethods = true)  //告诉SpringBoot这是一个配置类 == xml配置文件
public class MyConfig {
 
    /**
     * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
     * @return
     */
    //给容器中添加组件,相当于bean标签,以方法名作为组件的id。 返回类型是组件类型,返回值就是组件在容器中的实例。
    @Bean
    public User user01(){
        return new User("zhangsan",18);
    }
    // 如果不想用方法名作为组件的id 可以修改Bean中的value属性,自定义组件id
    @Bean("tom") //此时组件id就不再是tomcatPet,而是tom
    public Pet tomcatPet(){
        return new Pet("tomcat");
}

Full模式和Lite模式(新版本增加)

配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

2、@Bean、@Component、@Controller、@Service、@Repository

这些注解与Spring中学习的作用一致,不再解释。

3、@ComponentScan、@Import

ComponentScan是组件扫描的意思。

@Import()

Import注解后面填的是类的数组,作用是给容器中自动创建出这两个类型的组件、且默认组件的名字是全包名。

(可以与@Bean方法创建出的组件是方法名相对比)。

4、@Conditional

条件装配

@ConditionalOnBean(name = "tom")

此注释表示:只有在IOC容器中有tom名称的类才将这个注释挂载的类/方法注册。

2.2、原生配置引入@ImportResource

在一些老的项目或者第三方包引入的时候,很可能还是采用老版的xml方式注册组件,可以在任一配置类上加上此注解,导入xml的地址就可以引入。

使用方式:

1、首先创建xml配置文件,写入一个bean

<bean id="user02" class="com.atguigu.boot.bean.User">
        <property name="age" value="20"/>
        <property name="name" value="xcc"/>
 </bean>

2、在任意一个配置类上加上@ImportResource注解

@ImportResource("classpath:beans.xml")
public class MyConfig {
}

2.3 配置绑定

1、@ConfigurationProperties

一些需要抽离的会改变的配置,之前会以properties文件的形式存储,然后通过读取文件,来放入javabean中,但是该注解不必如此麻烦。

只要将需要配置的类加入容器中,再使用@ConfigurationProperties注解,就能够自动将applicaton.properties文件中的属性注入该类。

使用步骤:

1、创建实体类,然后加上@Component注解,将该类注册进容器中。

2、使用@ConfigurationProperties注解,prefix的含义是,所有mycar开头的属性就是要注入的配置内容。

/**
 * 只有在容器中的组件,才会拥有springboot的强大功能
 */
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
    //一些属性get、set方法云云       
}

3、在application.properties中配置需要注入的属性

mycar.brand = BYD
mycar.price = 100000

注意:如果该类是引入包里的类,不方便直接在要注入的类上加注释

可以在配置文件中如此声明

@EnableConfigurationProperties(Car.class)

该注释的作用有2个:

1、开启配置绑定功能。

2、把组件自动注册到容器中。

3、自动配置原理入门

3.1 引导加载自动配置类

 为什么springboot可以不用我们使用xml文件(仅使用Bean)就可以向容器中注册组件?

原因在于springboot主程序下的声明注解:

  @SpringBootApplication

该注解由3个注解复合而成:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

@SpringBootConfiguration:

这个注解其实就是一个Configuration注解,声明主程序也是一个特殊的配置类。

@ComponentScan

这个注解起到了扫描包的作用,指定扫描包的路径

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

1、@AutoConfigurationPackage

自动配置包,点进去可以看到:

@Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
 
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

首先Import导入了一个组件,然后这个组件的功能是用来注册扫描的包下所有的组件。

2、@Import(AutoConfigurationImportSelector.class)

有选择的自动配置一些组件。

1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4、从META-INF/spring.factories位置来加载一个文件。
默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

总的来说:springboot将所有环境的配置全部写在了一个一个工厂的配置文件里。

3.2 按需开启自动匹配项

127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
原理:按照条件装配规则(@Conditional),将选择的配置加载。

3.3 修改默认配置

@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}

给容器中加入了文件上传解析器;

springboot帮我们底层封装了一个注解方法,将不符合规范的命名也更正了。

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

*******总结********:

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

xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties  

3.4 配置流程

4、开发工具

4.1 lombok

lombok可以简化javabean的编写。

当我们创建javabean类的时候,总要编写其getset方法,toString方法、有参无参构造器,很烦而且代码很多不清晰。

可以加lombok注解简化编写。

使用前提:

1、添加lombok的依赖。

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2、在插件市场安装lombok插件。

使用说明:

@ToString
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pet {
    private String name;
 
}

@Data:自动编写其get/set方法。

@ToString:自动重写其toString方法。

@NoArgsConstructor:编写无参构造器。

@AllArgsConstructor:编写有参构造器。需要注意的是,有参构造器默认是将所有的参数都构造,如果要想限定个数个参数构造,还是需要自己写。

@Slf4j:日志注解。可以通过log.info在控制台打印消息。

4.2 dev-tools

热更新,在修改了方法或页面时,只需要用dev-tools(Ctrl+F9)就行重新编译,速度要比重启项目快一些

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

4.3 Spring Initailizr(项目初始化向导)

在创建项目的时候,只需要勾选环境,就会自动帮我们搭建项目所需要的环境。

所以我们只需要关注项目本身的代码。

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

相关文章

  • SpringBoot配置绑定方法详解

    SpringBoot配置绑定方法详解

    配置绑定是SpringBoot其中一个底层功能,SpringBoot把配置绑定的过程变得更加简单,传统java将常用的配置放到配置文件properties中,之后将这些配置绑定到javabean中
    2022-10-10
  • Springboot视频接口报大量的ClientAbortException找不到原因的解决

    Springboot视频接口报大量的ClientAbortException找不到原因的解决

    本文主要介绍了Springboot视频接口报大量的ClientAbortException找不到原因的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • MyBatis简介与配置MyBatis+Spring+MySql的方法

    MyBatis简介与配置MyBatis+Spring+MySql的方法

    MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。这篇文章主要介绍了MyBatis简介与配置MyBatis+Spring+MySql的方法,需要的朋友可以参考下
    2017-04-04
  • Java实现CORS跨域请求的实现方法

    Java实现CORS跨域请求的实现方法

    本篇文章主要介绍了Java实现CORS跨域请求的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Java字符编码原理(动力节点Java学院整理)

    Java字符编码原理(动力节点Java学院整理)

    Java开发中,常常会遇到乱码的问题,一旦遇到这种问题,常常比较烦恼,大家都不想承认是自己的代码问题,其实搞明白编码的本质过程就简单多了,接下来小编给大家带来java字符编码原理,要求看看吧
    2017-04-04
  • Java listener简介_动力节点Java学院整理

    Java listener简介_动力节点Java学院整理

    这篇文章主要介绍了Java listener简介,可以用于统计用户在线人数等,有兴趣的可以了解一下
    2017-07-07
  • SpringBoot万字爆肝高级配置

    SpringBoot万字爆肝高级配置

    SpringBoot不仅支持常规的properties配置文件,还支持yaml语言的配置文件,yaml是以数据为中心的语言,在配置数据的时候具有面向对象的特征。application.properties是比较常见的配置文件,SpringBoot的全局配置文件的作用是对一些默认配置的配置值进行修改
    2022-07-07
  • java的异常与处理机制分析【附面试题】

    java的异常与处理机制分析【附面试题】

    这篇文章主要介绍了java的异常与处理机制,结合实例形式分析了Java异常与处理机制的概念、原理、相关操作技巧与注意事项,并附带面试题分析供大家参考,需要的朋友可以参考下
    2019-05-05
  • java static块和构造函数的实例详解

    java static块和构造函数的实例详解

    这篇文章主要介绍了java static块和构造函数的实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握Java static关键字的函数方法,需要的朋友可以参考下
    2017-09-09
  • Java中JSON字符串进行各种转换的方法小结

    Java中JSON字符串进行各种转换的方法小结

    Gson和Hutool的JSONUtil都是常用的用于处理JSON数据的工具库,它们提供了简单易用的API来进行JSON字符串的解析、转换和操作,下面就跟随小编一起学习一下如果使用他们实现JSON字符串的各种转换吧
    2024-01-01

最新评论