SpringBoot原理(源码跟踪)

1 起步依赖

起步依赖的原理就是Maven的依赖传递,当我们引入了 spring-boot-starter-web 之后,maven会通过依赖传递特性,将web开发所需的常见依赖都传递下来。

2 自动配置

SpringBoot的自动配置是指当spring容器启动了以后,一些配置类、bean对象自动交给了spring容器保管,不需要手动去声明,大大简化了我们的开发。在我们的起步依赖中就有许多已经在启动spring容器时就交给其管理的类,我们可以直接注入并使用。

那么在spring项目启动的初始化时一开始总共将多少配置类交由了spring容器管理呢。

3 自动配置类查看

我们从spring启动项的关键注解@SpringBootApplication开始挖掘源码来找到配置类。

less 复制代码
@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}
)}
)

这是@SpringBootApplication注解上标记的注解,我们继续看@EnableAutoConfiguration注解,可以看到注解上有

python 复制代码
@Import({AutoConfigurationImportSelector.class})

@Import是将类导入spring容器的方法之一,还有一种方法是@ComponentScan 组件扫描。

继续看AutoConfigurationImportSelector类:

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

其中有getAutoConfigurationEntry的方法,也写在AutoConfigurationImportSelector类之中

kotlin 复制代码
protected 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 AutoConfigurationEntry(configurations, exclusions);
    }
}

configrations是配置的意思。其中有一个getCandidateConfigurations的方法,是获得候选配置的意思,而后续的代码还有checkExcludedClasses和configurations.removeAll(exclusions)的方法,可以推测出这是一个获得spring所有起步依赖种的配置类的方法,并在后续将和已经导入依赖无关的配置类排除在外的操作。那我们直接去看getCandidateConfigurations方法,应该就能找到springboot的源代码是如何获取所有配置类的了。

arduino 复制代码
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).getCandidates();
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

可以看到断言中出现了非常关键的信息:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

最终在org.springframework.boot.autoconfigure:3.0.2下找到了该目录

其中包含了142项启动时交由spring容器保管的类

当然,并不是spring一启动就将这些配置类全部一股脑交由spring容器管理,根据getAutoConfigurationEntry方法中可以得知,对于与目前导入依赖没有关系的配置类,他们并不会加入到spring容器之中,这大大提升了spring启动的速度。

相关推荐
啦工作呢42 分钟前
Sass:CSS 预处理器
开发语言·后端·rust
大鱼七成饱1 小时前
Rust工具不顺手?VSCode一站式丝滑配置
后端
37手游后端团队1 小时前
如何利用cursor高效重构代码
人工智能·后端
IT_陈寒1 小时前
SpringBoot 性能优化的 7 个冷门技巧,让你的应用快如闪电!
前端·人工智能·后端
canonical_entropy1 小时前
从“华丽的诡辩”到“构造的第一性原理”:我如何误解并最终拥抱广义可逆计算
人工智能·后端·低代码
用户4099322502122 小时前
PostgreSQL查询的筛子、排序、聚合、分组?你会用它们搞定数据吗?
后端·ai编程·trae
前端搞毛开发工程师2 小时前
Ubuntu 系统 Docker 安装避坑指南
前端·后端
心月狐的流火号2 小时前
Go语言错误处理
后端·go
Cache技术分享2 小时前
201. Java 异常 - 如何抛出异常
前端·javascript·后端
SimonKing2 小时前
弃用html2canvas!新一代截图神器snapdom要快800倍
java·后端·程序员