自动配置的原理

1,依赖管理

一个项目中的jar包是依赖于他的父项目的,因此在每个项目中都有下面的依赖。

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

从spring-boot-dependencies点进去,会发现他的父项目的一个依赖。

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.4.4</version>
  </parent>

然后再点进去会发现其中申明了我们开发中所用到的jar包的所有版本,因此我们在添加依赖的时候,是可以不指定版本的,因为在springboot是有默认的版本的,但是如果我们申明了版本的话,就会重新的加载新的版本。
在这里插入图片描述
我们也可以在当前的项目中重新修改版本。首先查看他用的key是什么。例如下面的样子。

    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>

2,开发导入starter场景启动器

1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的  *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.3.4.RELEASE</version>
  <scope>compile</scope>
</dependency>```

3,自动配置的基本原理

1,查看容器中的所有的组件

在这里插入图片描述
下图是其中的一些组件
在这里插入图片描述
springboot为我们自动的配置好了tomcat,在 web-starter的下面自动的添加了依赖。

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.4.4</version>
      <scope>compile</scope>
    </dependency>

同时也自动配好SpringMVC,引入SpringMVC全套组件,自动配好SpringMVC常用组件(功能)
自动配好Web常见功能,如:字符编码问题,SpringBoot帮我们配置好了所有web开发的常见场景

默认的包结构

在这里插入图片描述主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来,无需以前的包扫描配置
• 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.atguigu") 或者@ComponentScan 指定扫描路径

@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")

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

2.关于容器的一些内容

(1)向容器中添加组件
例如有两个类,一个person,一个pet。

package com.example.demo.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

@AllArgsConstructor
@Data
@ToString
public class person {
    private String name;
    private  int age;
}
package com.example.demo.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

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

创建一个配置类。

package com.example.demo.config;

import com.example.demo.bean.person;
import com.example.demo.bean.pet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//告诉springboot这是一个配置类
public class config {
    //返回值代表的是组件的类型,方法的名称代表的是组件的名字。
    @Bean
    public person person01(){
        return new person("张三",19);
    }
    //或者用下面的方式在@Bean里面修改实例的名称
    @Bean("哈哈")
    public pet pet02(){
        return new pet("小王");
    }
}

@Configuration这个注解是为了告诉springboot这是一个配置类。同时加了这个注解的类也会当作组件放到容器中。
在配置类中写方法,方法的名字代表的是组件的名字,方法的返回值,代表的是组件的类型,同时在@Bean中也可以修改组件的名称,@Bean代表的是在容器中注册组件。
在这里插入图片描述
在@Configuration中有一个proxyBeanMethods的属性,默认是true。

在这里插入图片描述
proxyBeanMethods:代理bean的方法,方法有两种,分别是Full和Lite。
Full(proxyBeanMethods = true),保证每个@Bean方法被调用多少次返回的组件都是单实例的,也就是无论调用那个方法多少次,调用的都是同一个组件,同时因为在每次启动springboot之前,都要检查容器中是否有这个组件,因此springboot启动的非常的慢,但是如果存在组件依赖的话,必须采取这种方式,是为了使得另一个组件依赖的组件是同一个组件,就像上面的人和狗,一个人的狗,必定是同一个狗,不可能因为调用几次,狗的名字就变了。
Lite(proxyBeanMethods = false),每个@Bean方法被调用多少次返回的组件都是新创建的,springboot启动会很快。
组件依赖必须使用Full模式默认。其他默认是Lite模式
在类上面标注这些注解都会讲将组件注册到容器中,@Bean、@Component、@Controller、@Service、@Repository
@ComponentScan是组件扫描的注解。
@Import注释是加在一个配置类的上面或者是一个组件的上面,意思是向容器中添加组件,名字是全类名。
在这里插入图片描述
在这里插入图片描述
像上面的样子。
@Conditional 条件装配:满足Conditional指定的条件,则进行组件注入。
ctrl+H是打开继承树。
在这里插入图片描述
@ConditionalOnMissingBean代表的是容器中没有这个这个组件才怎么样。
@ConditionalOnBean代表的是容器中有这个组件才怎么样。
@ConditionalOnWebApplication代表的是当前的项目是web项目才怎么样
@ConditionalOnClass代表的是当容器中有某一个类的时候才怎么样
@ConditionalOnMissingClass代表的是当前容器中没有某个类的时候才干什么。
@ConditionalOnResource当项目的类路径中存在某一个资源的时候才干什么。
@ConditionalOnJava当时某一些在指定的java版本的时候才干什么。
@ConditionalOnNotWebApplication当当前的项目不是web应用的时候才干什么。

3,原生配置文件的引入。

@ImportResource:
当有的项目中有bean.xml的配置文件的时候,我们不想用@bean一点一点的迁移,那么就可以将这个注解添加到任意的一个配置类的上面,那么这个bean.xml写的组件,便会自动的添加到容器中。

4,配置绑定

Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用。
(1)可以使用在@Component + @ConfigurationProperties。@Component代表的是将组件注册到容器中,因为只有容器中的组件才拥有springboot强大的功能,@ConfigurationProperties是和配置文件中的属性进行绑定。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
(2)使用@EnableConfigurationProperties + @ConfigurationProperties

@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
4,原理入门

(1),扫描main程序所在的包并且向其中批量的注册组件。

@SpringBootApplication是一个合成注解。
在这里插入图片描述@SpringBootConfiguration他的内部同样是一个合成注解。
在这里插入图片描述
因此,@SpringBootConfiguration和@Configuration的作用是一样的,也是标注这个类是一个配置类。
@ComponentScan是配置组件扫描范围的一个注解。
@EnableAutoConfiguration深入其中。
在这里插入图片描述
我们发现他主要是由@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)这两个注解组成,点开@AutoConfigurationPackage,自动配置包,指定了默认的包规则。点开@AutoConfigurationPackage,在其中@Import导入了一个Registrar组件,这个组件的主要作用是批量的注册一些组件。
在这里插入图片描述
点开Registrar。
在这里插入图片描述
AnnotationMetadata metadata代表的是注解@AutoConfigurationPackage的原信息,也就是这个注解标在了哪里,这个注解是标在mainapplication上面,因为上面标注的是合成的注解。
在这里插入图片描述
new AutoConfigurationPackages.PackageImport(metadata)得到的是包名,即main方法所在的那个包的包名。
在这里插入图片描述
这行代码的意思就是将这个包下的全部自定义组件注册到容器中。

(2) 点开@Import(AutoConfigurationImportSelector.class),他实现了最主要的接口是DeferredImportSelector,这个接口继承了ImportSelector接口,ImportSelector这个接口的调用地方是在spring容器处理Import注解的时候,如果@import注解导入的类实现了ImportSelector接口,则会调用selectImports方法获取Import的类。基于被引入的Configuration类的AnnotationMetadata信息选择并返回需要引入的类名列表;
ImportSelector的实现和@import通常在处理方式上是一致的,可以在所以的配置类,就是@Configuration标记的类处理完成后在进行筛选;
DeferredImportSelector接口实现了ImportSelector接口,表明他们作用差不多,DeferredImportSelector接口在所有的@Configuration处理完成之后才会调用,在需要筛选的引入类型具备@Conditional(条件注入指定类的时候)非常有用;最后会执行selectImports方法。

AutoConfigurationImportSelector流程分析

DeferredImportSelector会通过getImportGroup返回执行的类,然后执行内部类AutoConfigurationGroup方法的process方法,然后执行getAutoConfigurationEntry方法,我们就从AutoConfigurationImportSelector的process开始:
通过process的getAutoConfigurationEntry来获取自动装配的Entry对象:
在这里插入图片描述
然后进到getCandidateConfigurations方法,getCandidateConfigurations就加载出了spring-boot-autuator-atoconfig包下META-INF\spring,factories文件,第一次的时候cache里面是空的,就会通过classloader加载META-INF/spring.factories文件,通过配置的key/vlaue保存到缓存中.给后面使用:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
虽然这些场景的所有自动配置启动的时候默认全部加载。但是,xxxxAutoConfiguration按照条件装配规则(@Conditional),最终会按需配置。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值