springboot中自动配置笔记

springboot中自动配置笔记

简介

刚开始学习springboot的时候有一些自动配置的细节笔记,记录一下

讲解

1、spring-boot-starter-parent

​ 在"pom.xml"文件当中,我们可以看到下面的配置

 <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.6.RELEASEversion>
        <relativePath/> 
 parent>

​ 这个是springboot的父项目,然后我们点击这个spring-boot-starter-parent,进入进去发现如下:

  <parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-dependenciesartifactId>
    <version>2.2.6.RELEASEversion>
    <relativePath>../../spring-boot-dependenciesrelativePath>
  parent>

​ 还有一个父项目(套娃),继续点击spring-boot-dependencies,向下拉可以发现各种各样的依赖版本:

springboot中自动配置笔记_第1张图片

结论:

spring-boot-dependencies是Spring Boot的版本仲裁中心,一般来说我们导入依赖是不需要写版本的,基本上的依赖版本都会在spring-boot-dependencies进行管理,方便我们进行开发。

2、spring-boot-starter(启动器)

​ 既然上面只是对版本进行管理,那么我们的依赖是怎么导入的呢?我们继续观察“pom.xml”,

我们可以看到这个依赖:

<dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
dependency>

​ 可以看到spring-boot-starter-web跟上面的spring-boot-starter-parent只是相差的后面,一个是web一个是start,这个在springboot当中还是挺常见的。

我们点击spring-boot-starter-web,发现很多和web相关的依赖,例如:json、tomcat等:

springboot中自动配置笔记_第2张图片

结论:

​ spring-boot-starter是spring-boot场景启动器,而spring-boot-starter-web帮我们导入了web模块正常运行所依赖的组件,其中依赖的版本都由spring-boot-starter-parent帮助我们进行仲裁。

​ 类似的其实spring boot将所有功能场景都抽取了出来,做成了一个个starts,当我们需要什么时,只需要在项目当中引入这些starter就能将相关场景的依赖都导入进来,并且版本都不需要我们进行控制,因为版本在spring-boot-starter-parent当中就已经被控制了,所以说非常方便。比如说我们需要邮件开发的场景,我们就只需要导入spring-boot-starter-mail,他就把相对应的依赖导入进来。starters介绍的官方文档:传送门

3、主程序入口类

​ 主程序入口类是这样:

@SpringBootApplication
public class SpringBoot01HelloworldQuickApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot01HelloworldQuickApplication.class, args);
    }

}

其中 @SpringBootApplication::

​ Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot 就应该运行这个类的main方法来启动SpringBoot应用。

我们点开 @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

​ Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类。我们点击进去,会发现它是由@Configuration组成的,而@Configuration就是spring中的注解,标志一个配置类。

@EnableAutoConfiguration:

​ 开启自动配置功能,加上@EnableAutoConfiguration之后,springboot能够帮助我们自动配置这个注解,相当于开启自动配置功能。

@EnableAutoConfiguration具体是什么样的呢?我们点击@EnableAutoConfiguration进去,发现:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

​ 我们又发现了@AutoConfigurationPackage这个注解,我们继续点击进去发现:

@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {}

​ 我们发现了spring的底层注解@Import,该注解的作用是给容器中导入一个组件,组件由括号中的内容决定。也说明了@AutoConfigurationPackage是由@Import中导入的这个类起作用。

​ 我们继续点击Registrar这个类,发现

   static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
        }
    }

​ 我们在registerBeanDefinitions设置一个断点,然后调试

springboot中自动配置笔记_第3张图片

spring自动配置04

springboot中自动配置笔记_第4张图片

包结构:

springboot中自动配置笔记_第5张图片

​ 发现metadata传入的就是主类,而(new AutoConfigurationPackages.PackageImport(metadata))则是得到了主类所在的包。这其实也就说明了 @AutoConfigurationPackage的作用:将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器

​ 接着我们发现在@AutoConfigurationPackage下面还有一个@Import({AutoConfigurationImportSelector.class})注解。我们点进AutoConfigurationImportSelector,发现这么一个函数

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

同理设置断点调试

springboot中自动配置笔记_第6张图片

发现124个自动配置类

springboot中自动配置笔记_第7张图片

​ 那么该类的功能就是将一些需要的配置类导入进来并且配置好,比如说我们需要aop功能,那么它就将aop的自动配置类org.springframework.boot.autoconfigure.aop.AopAutoConfiguration导入了进来,并且配置好。有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。

​ 其实Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将 这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;以前我们在spring中需要自己配置的东西,自动配置类都帮我们完成了。整体的配置都在spring-boot-autoconfigure-2.2.6.RELEASE.jar中(springboot版本不同,这个可能版本也会不同)

springboot中自动配置笔记_第8张图片

spring.factories文件内容:

springboot中自动配置笔记_第9张图片

发现了前面调试的相同的内容

然后我们打开AopAutoConfiguration:

springboot中自动配置笔记_第10张图片

里面都是一些和配置相关的内容

4.以HttpEncodingAutoConfiguration为例讲解学习的到一些东西

首先我们需要找到这个类,我是使用idea按下ctrl+N就可以进行搜索

springboot中自动配置笔记_第11张图片

HttpEncodingAutoConfiguration的内容如下:

@Configuration(
    proxyBeanMethods = false
)//表示配置类
@EnableConfigurationProperties({HttpProperties.class})//启动指定类的ConfigurationProperties功能,将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中

@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)//判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的,即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
	//只有这一个构造函数
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }

    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }

    @Bean
    public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
        return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);
    }
	... 
}
  • 注解@Configuration,这个在这里有所讲解,就是给容器中添加组件,也对应了下面的@Bean注解

  • 注解@EnableConfigurationProperties({HttpProperties.class}),作用是启动指定类的ConfigurationProperties功能,将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中,并且我们看到HttpEncodingAutoConfiguration只有一个构造函数,就是将HttpProperties传入。

  • 进入HttpProperties中,发现

    @ConfigurationProperties(
        prefix = "spring.http"
    )
    public class HttpProperties {
    ...
    }
    

    而注解@ConfigurationProperties作用就是将配置文件中的内容注入到bean当中,说白了就是通过配置文件对HttpProperties对应的属性进行配置,可以看这个这个。这就说明了我们可以通过配置文件对HttpProperties进行配置然后影响到HttpEncodingAutoConfiguration这个类

结论:

  • xxxxAutoConfigurartion:自动配置类,主要负责给给容器中添加组件
  • xxxxProperties:封装配置文件中相关属性
  • 可以通过在application.properties中编写xxxxProperties的属性从而对xxxxAutoConfigurartion进行一些配置

总结

​ springboot的底层帮组我们做了很多的配置,所以现在使用起来springboot比较简单,但是底层的原理还是需要知道一些的,也可以加深的理解。感觉看老师讲的挺好的但是自己来写又说不出来,可能是还是没有理解够吧。

你可能感兴趣的:(springboot)