• springboot 自动配置原理


     使用版本:

                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.5.0</version>
                </dependency>

    启动器:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    spring-boot-starter-==web==:

    ​ spring-boot-starter:spring-boot场景启动器;帮我们导入了web模块正常运行所依赖的组件;

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

    2、主程序类,主入口类

    /**
     *  @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
     */
    @SpringBootApplication
    public class HelloWorldMainApplication {
        public static void main(String[] args) {
            // Spring应用启动起来
            SpringApplication.run(HelloWorldMainApplication.class,args);
        }
    }

    3、流程分析

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

    @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:配置类上来标注这个注解;

    ​ 配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component

    @EnableAutoConfiguration:开启自动配置功能;

    ​ 以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;

    @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {

    @AutoConfigurationPackage:自动配置包

    ​ @Import(AutoConfigurationPackages.Registrar.class):

    ​ Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class;

    ==将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;==

    ​ @Import(EnableAutoConfigurationImportSelector.class);

    ​ 给容器中导入组件?

    EnableAutoConfigurationImportSelector:导入哪些组件的选择器;

    ​ 将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;

    ​ 会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件;

    AutoConfigurationImportSelector.class
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            }
            AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
        protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            }
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
            List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                    getBeanClassLoader());
            Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                    + "are using a custom packaging, make sure that file is correct.");
            return configurations;
        }

    4、以HttpEncodingAutoConfiguration为列分析

    // 表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
    @Configuration(proxyBeanMethods = false)

    // 启动指定类的ConfigurationProperties功能;将配置文件中对应的值和ServerProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中 @EnableConfigurationProperties(ServerProperties.
    class)

    // Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;    判断当前应用是否是web应用,如果是,当前配置类生效 @ConditionalOnWebApplication(type
    = ConditionalOnWebApplication.Type.SERVLET)

    // 判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器; @ConditionalOnClass(CharacterEncodingFilter.
    class)

      // 判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的
      // 即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;

    @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(); }
       // 给容器中添加一个组件,这个组件的某些值需要从properties中获取 @Bean
       // 判断容器没有这个组件? @ConditionalOnMissingBean
    public 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; }

    根据当前不同的条件判断,决定这个配置类是否生效?

    一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

    所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功能对应的这个属性类

    // 从配置文件中获取指定的值和bean的属性进行绑定
    @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { /** * Server HTTP port. */ private Integer port; /** * Network address to which the server should bind. */ private InetAddress address;

    5总结:

    1)、SpringBoot启动会加载大量的自动配置类

    2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

    3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)

    4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;

    来源:尚硅谷课程

  • 相关阅读:
    人月神话 另外一面
    python论文爬取(五)
    Python词云
    python安装wordcloud库出错及其解决办法(使用命令行安装)
    人月神话 祸起萧墙
    python论文爬取(四)
    个人课程总结
    python论文爬取(三)
    python论文爬取(一)
    win10子系统ubuntu开机启动ssh服务
  • 原文地址:https://www.cnblogs.com/zcjyzh/p/15818145.html
Copyright © 2020-2023  润新知