SpringBoot 自动配置原理

一、项目的主配置类注解@SpringBootApplication()

SpringBoot 的标准启动入口如下:

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

通过标准启动入口的代码可以看出,SpringBoot 启动类的核心注解是@SpringBootApplication。源码如下:

根据源码,可以看出@SpringBootApplication主要包含3个注解:@SpringBootConfiguration 、@EnableAutoConfiguration 、@ComponentScan。

二、@SpringBootConfiguration

作用:继承自@Configuration,标注在类上表示这是一个 SpringBoot 的配置类,允许在上下文中注册额外的bean或者导入其他配置项。源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

三、@ComponentScan

作用:提供与 Spring xml 的 context:component-scan 并行的支持。自动扫描并加载符合条件的组件或者bean , 将bean定义加载到IOC容器中 。扫描被@Compent()、@Service、@Controller注解的bean,注解是会默认扫描启动类所在的包下的所有的类,也可以自定义不扫描一些bean。源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

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

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

四、@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 {};
}

在源码中可以看出@EnableAutoConfiguration主要包含两个注解:@AutoConfigurationPackage、@Import。

1️⃣@AutoConfigurationPackage自动导入配置包
源码包含了@Import({Registrar.class}),再点进去发现是批量注册组件,而默认扫描路径就是与主启动类所在的包,也就是主启动类所在的包下面,所有的组件会被扫描注册到IoC容器中。这就解释了为什么要把自己的组件写到与主启动类同包下。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

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

@Import 为Spring的注解,导入一个配置文件,在SpringBoot中为给容器导入一个组件,而导入的组件由 AutoConfigurationPackages.class的内部类Registrar.class 执行逻辑来决定是如何导入的。

2️⃣@Import
@EnableAutoConfiguration底层原理是使用@Import导入一些配置类,实现Bean的动态加载。底层依赖于@Import导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供四种用法:

  1. 导入Bean
  2. 导入配置类
  3. 导入 ImportSelector 实现类。一般用于加载配置文件中的类。
  4. 导入 ImportBeanDefinitionRegistrar 实现类。

@EnableAutoConfiguration 内部使用第3种方法:@Import 导入 ImportSelector 实现类的方式加载配置类,即@Import(AutoConfigurationImportSelector.class),给容器导入组件。AutoConfigurationImportSelector:自动配置导入选择器,给容器中导入一些组件,自动配置核心功能的实现实际上是通过AutoConfigurationImportSelector来实现的。

META-INF/spring.factories配置文件中定义了大量的配置类,当SpringBoot 应用启动时,会自动加载这些配置类,根据@conditional注解按需初始化Bean ,从而实现了SpringBoot的自动配置。

3️⃣@Conditional(条件类.class)注解

作用:实现选择性的创建 Bean 操作。SpringBoot 提供的常用条件注解:

  1. ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
  2. ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
  3. ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
  4. ConditionalOnBean:判断环境中有对应Bean才初始化Bean

五、自动配置具体实现步骤

  1. SpringBoot启动的时候加载主启动类,通过@EnableAutoConfiguration开启自动配置功能。

  2. @EnableAutoConfiguration利用AutoConfigurationImportSelector给容器中导入一些组件。

  3. 通过protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)获取候选的配置和核心方法,扫描所有jar包类路径下"META-INF/spring.factories",通过@AutoConfigurationPackage自动配置包。

  4. 把扫描到的文件包装成Properties对象。

  5. 从properties中获取到EnableAutoConfiguration.class类名对应的值,并把它们添加在容器中。

  6. 整个过程就是将类路径下"META-INF/spring.factories"里面配置的所有EnableAutoConfiguration的值加入到容器中。

  7. 根据@Conditional中的条件判断,决定这个配置是否生效。

  8. 初始化Bean,自动配置完成。

总结:
SpringBoot通过@EnableAutoConfiguration开启自动装配,通过SpringFactoriesLoader最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JFS_Study

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

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

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

打赏作者

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

抵扣说明:

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

余额充值