springboot自动配置原理_面试必问的SpringBoot自动配置原理,还不来看看?

SpringBoot自动配置原理

前言:SpringBoot的最大的特点就是帮助我们自动配置了很多场景启动器,我们之前利用SSM开发一个项目时,那些繁琐的配置再也不需要自己配置了,自动配置原理也是面试必问的关于SpringBoot的知识点,今天我们进来聊聊SpringBoot的自动配置原理

package com.staticzz.springboot_quick;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/**
**@SpringBootApplication注解为核心注解
**
**/@SpringBootApplicationpublic class SpringbootQuickApplication {public static void main(String[] args) {
        SpringApplication.run(SpringbootQuickApplication.class, args);
    }

SpringBootApplication注解作用

@SpringBootApplication 标注在某一个类上,就说明这个类为SpringBoot应用的主配置类,SpringBoot就应该运行这个类的main方法来启动Springboot应用

以前我们开发一个SSM项目,需要利用配置文件进行相关配置,而SpingBoot利用了配置类进行自动配置,

这里配置类等同于配置文件,SpringBoot并且开启了自动配置,以前我们需要手动配置的东西

这里SpringBoot帮我们进行了自动配置

PS:自动配置原理也是SpringBoot的精髓所在

package com.staticzz.springboot_quick;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**@SpringBootApplication注解标注在某一个类上,
就说明这个类为SpringBoot应用的主程序类
SpringBoot就应该运行这个类的main方法来启动Springboot应用
**/
@SpringBootApplication
public class SpringbootQuickApplication {

    public static void main(String[] args) {

        SpringApplication.run(SpringbootQuickApplication.class, args);
    }
}

那@SpringBootApplication这个注解与自动配置又有什么关系呢?

接下来我们Ctrl+左键,进入到这个注解中来查看 @SpringBootApplication 这个注解里到底配置了什么?我们先来进入到@SpringBootApplication这个注解中,看看它底层调用了什么注解

动图演示:

02fc9be63becb92e30ece23f123e83f1.png

我们观察到@SpringBootApplication注解,继承了@SpringBootConfiguration注解

而@SpringBootConfiguration注解又继承了Spring底层的注解@Configuration注解

凡是标注该注解的类都是配置类

那现在也只是知道了@SpringBootApplication注解一层一层的实现了Spring底层的@Configuration注解,被标注后称为配置类!那说了这篇文章讲的是SpringBoot的自动配置?配置有了,自动呢?

eea3a1055b755b56239a7e4da103ff6a.png

我没有骗人哦!确实是有自动配置的!而且SpringBoot也确确实实帮我们做了自动配置

0e2bba68a3f26bbc05e60693101bcc0a.png先上一张动态演示图,瞧瞧

907bc83ee763ead630faa9706dbb7cd2.png

第一步 ctrl+右键 进入了@EnableAutoConfiguration这个注解

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited

/**
**这个注解为自动导包的注解
**/
@AutoConfigurationPackage

/**
**这个为开启自动配置选择器的注解
**/
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     * @return the classes to exclude
     */
    Class>[] exclude() default {};

    /**
     * Exclude specific auto-configuration class names such that they will never be
     * applied.
     * @return the class names to exclude
     * @since 1.3.0
     */
    String[] excludeName() default {};

}

有没有发现我在这动态演示中,重点高亮了两个注解

@AutoConfigurationPackage

@Import(EnableAutoConfigurationImportSelector.class)

这两个注解分别是什么意思 废话不多说 下面看!

@AutoConfigurationPackage 自动扫描包

@Import(EnableAutoConfigurationImportSelector.class) 导入自动配置类选择器组件

来看源码分析

@AutoConfigurationPackage

源码展示:

/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

   //这个方法为SpringBoot帮助我们自动扫描包获取获取包名并进行注册
   @Override
   public void registerBeanDefinitions(AnnotationMetadata metadata,
   BeanDefinitionRegistry registry) {
        register(registry, new PackageImport(metadata).getPackageName());
         }


    @Override
    public Set determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImport(metadata));
        }
    }

动态展示: 

自动扫描包

注意观察动图中我高亮的部分

自动扫描包源码演示

结论:SpringBoot在启动时,会自动扫描主程序类所在的包下的所有子包

来看源码分析:

@Import(EnableAutoConfigurationImportSelector.class)

源码展示:

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    try {
     AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
       .loadMetadata(this.beanClassLoader);
 //获取到注解元数据      
 AnnotationAttributes attributes = getAttributes(annotationMetadata);
 //获取到配置类封装为一个list数据
 List configurations = getCandidateConfigurations(annotationMetadata,
 attributes);
 configurations = removeDuplicates(configurations);
 configurations = sort(configurations, autoConfigurationMetadata);
 Set exclusions = getExclusions(annotationMetadata, attributes);
 checkExcludedClasses(configurations, exclusions);
 configurations.removeAll(exclusions);
 configurations = filter(configurations, autoConfigurationMetadata);
 fireAutoConfigurationImportEvents(configurations, exclusions);//返回给容器return configurations.toArray(new String[configurations.size()]);
   }catch (IOException ex) {throw new IllegalStateException(ex);
        }
    }

@Import(EnableAutoConfigurationImportSelector.class) 这个注解的作用选择自动配置类并扫描进容器中,

动态展示: 

导入自动配置类选择器组件

自动配置类选择器

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

SpringBoot就是通过这两个注解来自动帮助我们完成自动配置的,聪明的你学废了吗?

9b4642b727b9fc98d69d0bf19e57df1b.png

往期回顾

Redis持久化是如何做的?RDB和AOF对比分析

可能是史上很一道简单的JAVA面试题,但很多人都答错了

前、后端分离权限控制设计和实现思路,太强了!

留言区

                     12acc2451e8395848c6408052fba6a5c.png

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页