SpringBoot 自动装配原理及源码解析

目录

一、引言

二、自动装配原理

三、核心注解解析

[1、 @SpringBootApplication 注解](#1、 @SpringBootApplication 注解)

​编辑(1)@SpringbootConfiguration

(2)@ComponentScan

(3)@EnableAutoConfiguration

2、条件装配(Conditional系列注解)


一、引言

springboot 的自动装配(Auto-Configuration)是一种特性,它可以基于类路径上的条件以及属性文件中的设置自动配置 Spring 应用程序,简化开发人员需要编写的配置代码。

详情可以查阅:springboot参考指南

二、自动装配原理

自动装配实际上就是把第三方组件的Bean装载到IOC容器里,不需要开发人员再去写Bean相关的一个配置

三、核心注解解析

1、 @SpringBootApplication注解

通常只需要在SpringBoot应用启动类上加上 @SpringBootApplication 注解,就可以去实现自动装配。

@SpringBootApplication注解是一个复合注解,其主要包含三个重要的注解,@SpringBootConfiguration,@EnableAutoConfiguration和@ComponentScan

真正去实现自动装配的注解其实是 @EnableAutoConfiguration 注解。

(1)@SpringbootConfiguration

@SpringBootConfiguration 本质上就是 @Configuration,用于指定一个类是配置类。

(2)@ComponentScan

注解默认会扫描启动类所在的包下所有的类 ,为后续装配工作提供资源支持(也可以自定义不扫描某些包下的类)。

(3)@EnableAutoConfiguration

@EnableAutoConfiguration是自动配置的核心,它引导自动配置机制。

通过 @Import(AutoConfigurationImportSelector.calss)来引入AutoConfigurationImportSelector

AutoConfigurationImportSelector的作用是根据项目的依赖和配置情况,动态地选择并加载适合的自动配置类。

AutoConfigurationImportSelector的继承关系如下:

AutoConfigurationImportSelector 类通过重写实现了 ImportSelector接口中的selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IOC容器 中。

java 复制代码
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

ImportSelector 接口用于实现动态地选择需要被导入到容器中的配置类的逻辑

java 复制代码
public interface ImportSelector {
    /**
     * @param importingClassMetadata 用于描述使用了 @Import 注解的配置类的注解元数据。
     * @return 数组中的每个元素都是一个全限定类名,表示需要被导入到容器中的配置类。
     */ 
    String[] selectImports(AnnotationMetadata var1);
    /**
     * 提供一个可选的排除过滤器,决定哪些配置类应该被排除在外。
     * 默认返回 null,表示没有排除过滤器。
     */
    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null; // 默认没有排除过滤器
    }
}

getAutoConfigurationEntry方法通过一系列步骤,包括检查自动配置是否启用、获取候选配置、去除重复项、获取排除配置、检查排除的类是否有效、移除排除项、过滤配置,最终生成一个包含自动配置类和排除配置类的AutoConfigurationEntry对象。

getAutoConfigurationEntry方法是Spring Boot自动配置功能的核心,它确保了只有符合条件的自动配置类被加载到Spring应用上下文中。

java 复制代码
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(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.getConfigurationClassFilter().filter(configurations);
        // 触发自动配置导入事件
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        // 返回自动配置条目
        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
}

接下来,我们debug看一下具体各个步骤内容:

1、判断自动装配开关是否打开,默认是spring.boot.enableautoconfiguration=true,可以在application.properties或者application.yml中设置开启或关闭。

2、获取EnableAutoConfiguration注解中的exclude 和excluedeName

3、获取需要自动装配的所有配置类,读取META-INF/spring.factories

4、在spring boot中,spring.factories文件中列出了许多自动配置类,但是这并不意味着每次应用启动时所有这些配置都会被加载。Spring Boot采用了一种称为条件配置的机制,使得只有在特定条件满足时,相关的自动配置类才会被激活和加载。

我们继续进行debug

可以发现,configurations的size值变小了,意味着并不是所有的配置都被加载了进去。

2、条件装配(Conditional系列注解)

Spring Boot在进行自动装配时并不是会盲目的把所有类全部装配进去,而是会有选择的进行,通过@Conditional系列注解来实现选择,常见条件包括:

@ConditionalOnClass:当类路径中存在某个类时才生效。
@ConditionalOnMissingBean:当 Spring 上下文中不存在某个 Bean 时才生效。
@ConditionalOnProperty:当某个配置属性满足特定条件时才生效。
@ConditionalOnBean:当 Spring 上下文中存在某个 Bean 时才生效。

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

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

参考来源:SpringBoot 自动装配原理源码分析-CSDN博客

相关推荐
李长渊哦1 小时前
Java 虚拟机(JVM)方法区详解
java·开发语言·jvm
陌殇殇2 小时前
002 SpringCloudAlibaba整合 - Feign远程调用、Loadbalancer负载均衡
java·spring cloud·微服务
猎人everest3 小时前
SpringBoot应用开发入门
java·spring boot·后端
山猪打不过家猪5 小时前
ASP.NET Core Clean Architecture
java·数据库·asp.net
AllowM5 小时前
【LeetCode Hot100】除自身以外数组的乘积|左右乘积列表,Java实现!图解+代码,小白也能秒懂!
java·算法·leetcode
不会Hello World的小苗6 小时前
Java——列表(List)
java·python·list
二十七剑7 小时前
jvm中各个参数的理解
java·jvm
东阳马生架构8 小时前
JUC并发—9.并发安全集合四
java·juc并发·并发安全的集合
计算机小白一个8 小时前
蓝桥杯 Java B 组之岛屿数量、二叉树路径和(区分DFS与回溯)
java·数据结构·算法·蓝桥杯
White graces9 小时前
正则表达式效验邮箱格式, 手机号格式, 密码长度
前端·spring boot·spring·正则表达式·java-ee·maven·intellij-idea