springboot-自动配置
创始人
2024-02-21 03:20:40
0

一、简介

在搭建springboot应用的时候,无需像之前spring的时候,要一堆繁琐的配置文件之类的。一个main的方法,就能把springboot的项目run起来。和其他框架整合也是非常的简单,只需要使用到Enablexxxxx注解就可以搞起来。

二、原理

springboot的自动配置入手可以先从启动类入手:

@SpringBootApplication:SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot的应用;

2.1 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) })
// AutoConfigurationExcludeFilter的作用是扫描到的配置类名字如果在自动配置类名集合中,就不解析
public @interface SpringBootApplication {

  • @SpringBootConfiguration:Spring Boot的配置类;
    •    标注在某个类上,表示这是一个Spring Boot的配置类;
  • @Configuration:配置类上来标注这个注解;
    •    配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component
  • @EnableAutoConfiguration:开启自动配置功能;
    • 以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置,会帮我们自动去加载 自动配置类
  • @ComponentScan : 扫描包
    • 相当于在spring.xml 配置中 但是并没有指定basepackage,如果没有指定spring底层会自动扫描当前配置类所有在的包
  • TypeExcludeFilter
    • springboot对外提供的扩展类, 可以供我们去按照我们的方式进行排除
  • AutoConfigurationExcludeFilter
    • 排除所有配置类并且是自动配置类中里面的其中一个

2.2 @EnableAutoConfiguration

这个注解里面,最主要就是@EnableAutoConfiguration,直白的名字,一眼就知道是它来操作开启自动配置。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:将当前配置类所在的包保存在BasePackages的Bean里,供Spring的内部使用

2.2.1 @AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

注册了一个保存当前配置类所在的一个Bean,提供给spring-data-jpa 需要扫描@Entity

2.2.2 @Import(AutoConfigurationImportSelector.class)

可以看到,在@EnableAutoConfigurantion注解内使用到了@Import注解来完成导入功能,而AutoConfigurationImportSelector实现了DeferredImportSelectorSpring内部在解析@Import注解时会调用getAutoConfigurationEntry方法。

getAutoConfigurationEntry方法进行扫描具有META-INF/spring.factories文件的jar包

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}// 获取@EnableAutoConfiguration的属性AnnotationAttributes attributes = getAttributes(annotationMetadata);// 获取spring.factories中所有的AutoConfigurationList configurations = getCandidateConfigurations(annotationMetadata, attributes);// 去重(也就是按类名去重)configurations = removeDuplicates(configurations);// 获取需要排除的AutoConfiguration,可以通过@EnableAutoConfiguration注解的exclude属性,或者spring.autoconfigure.exclude来配置Set exclusions = getExclusions(annotationMetadata, attributes);// 根据:@EnableAutoConfiguration.exclude// @EnableAutoConfiguration.excludeName// spring.autoconfigure.exclude  进行排除checkExcludedClasses(configurations, exclusions);// exclusions 也排除configurations.removeAll(exclusions);// 获取spring.factories中的AutoConfigurationImportFilter对AutoConfiguration进行过滤// 默认会拿到OnBeanCondition、OnClassCondition、OnWebApplicationCondition// 这三个会去判断上面的AutoConfiguration是否符合它们自身所要求的条件,不符合的会过滤掉,表示不会进行解析了// 会利用spring-autoconfigure-metadata.properties中的配置来进行过滤// spring-autoconfigure-metadata.properties文件中的内容是利用Java中的AbstractProcessor技术在编译时生成出来的configurations = getConfigurationClassFilter().filter(configurations);// configurations表示合格的,exclusions表示被排除的,把它们记录在ConditionEvaluationReportAutoConfigurationImportListener中fireAutoConfigurationImportEvents(configurations, exclusions);// 最后返回的AutoConfiguration都是符合条件的return new AutoConfigurationEntry(configurations, exclusions);}

任何一个springboot应用,都会引入spring-boot-autoconfigure,而spring.factories文件就在该包下面。spring.factories文件是Key=Value形式,多个Value时使用,隔开,该文件中定义了关于初始化,监听器等信息,而真正使自动配置生效的key是org.springframework.boot.autoconfigure.EnableAutoConfiguration,如下所示:

等同于

@Import({

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
...省略
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

})

每一个这样的xxxAutoConfiguration类都是容器的一个组件,都假如到容器中,用它们来做自动配置;

springboot所以配置类表

每一个自动配置类进行配置功能;

相当:@EnableAutoConfiguration注解通过@SpringBootApplication被间接的在Spring Boot的启动类上,在SpringApplication.run()的内部就会执行到selectImports()方法,找到所有JavaConfig自动配置类对应的class,加载到Spring容器中

2.3 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {private final Encoding properties;public HttpEncodingAutoConfiguration(ServerProperties properties) {this.properties = properties.getServlet().getEncoding();}@Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));return filter;}

@Configuration(proxyBeanMethods = false)

  • 标记了@Configuration Spring底层会给配置创建cglib动态代理。 作用:就是防止每次调用本类的Bean方法而重新创建对象,Bean是默认单例的

@EnableConfigurationProperties(ServerProperties.class)

  • 启用可以在配置类设置的属性 对应的类
  • @xxxConditional根据当前不同的条件判断,决定这个配置类是否生效?

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

2.3.1 springboot的条件注解意思

@Conditional扩展注解作用

(判断是否满足当前指定条件)

@ConditionalOnJava

系统的java版本是否符合要求

@ConditionalOnBean

容器中存在指定Bean;

@ConditionalOnMissingBean

容器中不存在指定Bean;

@ConditionalOnExpression

满足SpEL表达式指定

@ConditionalOnClass

系统中有指定的类

@ConditionalOnMissingClass

系统中没有指定的类

@ConditionalOnSingleCandidate

容器中只有一个指定的Bean,或者这个Bean是首选Bean

@ConditionalOnProperty

系统中指定的属性是否有指定的值

@ConditionalOnResource

类路径下是否存在指定资源文件

@ConditionalOnWebApplication

当前是web环境

@ConditionalOnNotWebApplication

当前不是web环境

@ConditionalOnJndi

JNDI存在指定项

如:

 

  • @Configuration:表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件。
  • @ConditionalOnWebApplication:Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效。
  • @ConditionalOnClass:判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器。
  • @ConditionalOnProperty:判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的

即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的。

  • @EnableConfigurationProperties({ServerProperties.class}):将配置文件中对应的值和 ServerProperties绑定起来;并把 ServerProperties加入到 IOC 容器中。并注册ConfigurationPropertiesBindingPostProcessor用于将@ConfigurationProperties的类和配置进行绑定

 

ServerProperties通过 @ConfigurationProperties 注解将配置文件与自身属性绑定。

对于@ConfigurationProperties注解,它的作用就是把全局配置文件中的值绑定到实体类JavaBean上面(将配置文件中的值与ServerProperites绑定起来),而@EnableConfigurationProperties主要是把以绑定值JavaBean加入到spring容器中。

我们在application.properties 声明spring.application.name 是通过@ConfigurationProperties注解,绑定到对应的XxxxProperties配置实体类上,然后再通过@EnableConfigurationProperties注解导入到Spring容器中.

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...