SpringBoot---(7) SpringBoot底层原理探究之自动配置原理

一、SpringBoot的探究

1、POM文件
(1)父项目
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.4.4</version>
</parent>
  • 它的上级父项目为(SpringBoot的版本号的仲裁中心):
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>2.4.4</version>
</parent>

注意
它的上级父项目里面管理着SpringBoot应用里面的所有以来版本;以后我们导入依赖是不需要写版本号(没有再dependencies里面管理的依赖项目自然需要声明版本号)

(2)导入依赖
<!--SpringBoot框架web项目起步依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • spring-boot-starter-web

  • Spring-boot-starter:是SpringBoot的场景启动器;帮我们导入web模块正常运行所依赖的组件。

  • SpringBoot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目里面引入这些starter相关场景的所有的依赖都会导入进来,需要什么依赖就导入什么样场景的启动器即可。

启动器

2、主程序类(入口类)
/**
 * SpringBoot项目启动入口类
 */
//SpringBoot核心注解,主要用于开启spring自动配置
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        //让Spring应用启动起来
        SpringApplication.run(Application.class, args);
    }
}
  • @SpringBootApplication:

表示这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用,Spring Boot会自动扫描@SpringBootApplication所在类的同级包,其注解的源代码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
  • @SpringBootConfiguration:

SpringBoot的配置类,标注在某个类上,表示这是一个SpringBoot的配置类

  • @Configuration:

配置类上标注这个注解

3、自动配置原理
(1)自动配置原理:
1、SpringBoot启动的时候加载主配置文件,开启了自动配置功能@EnableAutoConfiguration
2、@EnableAutoConfiguration作用:

根据类路径中的 jar 包依赖为当前项目开启自动配置功能,例如,添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC的依赖并会对其进行自动配置,其底层源码如下:

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
  • @AutoConfigurationPackage:自动配置包,其底层源码如下:
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}
  • @Import:Spring底层注解,给容器中导入一个组件,导入组件由Registrar.class决定;
  • @Import({AutoConfigurationImportSelector.class})

导入哪些组件的选择器; 将所有需要导入的组件以全类名的方式返回并添加到容器中去;其会给 容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件,从而免去了手动 编写配置注入功能组件等功能工作。

  • AutoConfigurationImportSelector
  • A、可以查看里面的selectImports()方法的内容,并通过List< String > configurations=getCandidateConfigurations(...) 获取候选的配置类
    在这里插入图片描述
  • B、扫描所有jar包类路径下的META-INF/spring.factories
    在这里插入图片描述
    在这里插入图片描述
  • C、把扫描到的这些文件的内容包装成properties对象,再从properties对象中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把它们添加到容器中;也就是将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值添加到容器中
    在这里插入图片描述
  • D、每一个这样的xxxAutoConfiguration类都是容器中的每一个组件,都加入到容器中,用它们来做自动配置
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
..........
(3)解释自动配置原理(以HttpEncodingAutoConfiguration:Http编码自动配置为例)
@Configuration(
    proxyBeanMethods = false
)
@EnableConfigurationProperties({ServerProperties.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
解析各注解的作用:
  • @Configuration:表示这是一个配置类,也可以给容器中添加组件
    在这里插入图片描述
  • @EnableConfigurationProperties:启动指定类的ConfigurationProperties功能,将配置文件中对应的值和xxxProperties属性类绑定起来。
@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties {
	private final Encoding properties;
	public HttpEncodingAutoConfiguration(ServerProperties properties) {
    		this.properties = properties.getServlet().getEncoding();
	}


	@Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
    		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    		filter.setEncoding(this.properties.getCharset().name());
    		filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
    		filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
   		 return filter;
	}
}
  • @ConfigurationProperties:从配置文件中获取指定的值和Bean属性值进行绑定,并把xxxProperties加入到ioc容器中
  • @CondittionalOnWebApplication:Spring底层@Condittional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效
  • @CondittionalOnClass:判断当前项目是否有这个类,里面的 CharacterEncodingFilter是SpringMVC中进行乱码解决的过滤器
  • @ConditionOnProperty:判断配置文件中是否存在某个配置 “spring.http.encoding”;如果不存在,判断也是生效的。
  • @Bean:给容器添加组件,这个组件的某些值需要properties中获取,而前面的属性private final HttpEncodingProperties properties;已经和SpringBoot配置文件映射了,而只有一个有参构造方法的情况下,properties参数的值就会从ioc容器中获取出来。
#server.port=8080
#server.servlet.context-path=/

spring.profiles.active= test

#我们能配置的属性是来源于这个功能的properties类
spring.http.encoding.enabled=true
spring.http.encoding.charset=utf-8
spring.http.encoding.force=true
(4)总结
  1. SpringBoot在启动的时候从类路径下的META-INF/Spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类生效之后,就帮我们进行自动配置工作。
  2. 根据当前不同的条件,决定这个配置类是否生效,一但这个配置类生效,该配置类就会给容器中添加各种组件。这些组件的属性是从对应的properties类中获取的,而这些properties类里面的每一个属性又是和配置文件绑定的。
  3. 所有在配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能能对应的这个属性类;
  4. 需要通过在配置文件中启动debug=true属性,让控制台打印自动配置报告,我们就可以知道哪些自动配置类生效了。
(5)SpringBoot精髓

(1)SpringBoot自动会加载大量的自动配置类:xxxAutoConfiguration
(2)当我们需要的配置类在SpringBoot中没有,这时就要自己配置
(3)当这些配置类生效之后就会给容器中添加各种组件
(4)添加组件的时候,会从xxxProperties类中获取某些属性,我们就可以在配置文件中指定这些属性的值。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@烟雨倾城ゝ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值