it编程 > 编程语言 > Java

SpringBoot自动配置原理是什么?从启动器到spring.factories全解析

92人参与 • 2026-10-11 • Java

pom.xml

父工程

启动器

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter</artifactid>
</dependency>

如 spring-boot-starter-web 会帮我们自动导入 web 环境所有需要的依赖

主程序

@springbootapplication       //标注这个类是一个springboot的应用
public class springboot01application {
    //将springboot应用启动
    public static void main(string[] args) {
        springapplication.run(springboot01application.class, args);
    }
}

注解

注解名称注解作用
@springbootapplication标记为 springboot 的应用
@springbootconfiguration标记为 springboot 的配置
@enableautoconfiguration启用自动配置
@componentscan扫描当前主启动类同级的包
@configuration标记为 spring 配置类
@component标记为 spring 的组件
@autoconfigurationpackage自动配置包
@import({registrar.class})注册表
@import({autoconfigurationimportselector.class})自动导入选择器

autoconfigurationimportselector 类

getautoconfigurationentry() 方法

list<string> configurations = this.getcandidateconfigurations(annotationmetadata, attributes);

getcandidateconfigurations() 方法

protected list<string> getcandidateconfigurations(annotationmetadata metadata, annotationattributes attributes) {
    list<string> configurations = springfactoriesloader.loadfactorynames(this.getspringfactoriesloaderfactoryclass(), this.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;
}

getspringfactoriesloaderfactoryclass() 方法

protected class<?> getspringfactoriesloaderfactoryclass() {
    return enableautoconfiguration.class;
}

springfactoriesloader 类

loadfactorynames() 方法

public static list<string> loadfactorynames(class<?> factorytype, @nullable classloader classloader) {
    classloader classloadertouse = classloader;
    if (classloader == null) {
        classloadertouse = springfactoriesloader.class.getclassloader();
    }

    string factorytypename = factorytype.getname();
    return (list)loadspringfactories(classloadertouse).getordefault(factorytypename, collections.emptylist());
}

loadspringfactories() 方法

private static map<string, list<string>> loadspringfactories(classloader classloader) {
    map<string, list<string>> result = (map)cache.get(classloader);
    if (result != null) {
        return result;
    } else {
        hashmap result = new hashmap();

        try {
            enumeration urls = classloader.getresources("meta-inf/spring.factories");

            while(urls.hasmoreelements()) {
                url url = (url)urls.nextelement();
                urlresource resource = new urlresource(url);
                properties properties = propertiesloaderutils.loadproperties(resource);
                iterator var6 = properties.entryset().iterator();

                while(var6.hasnext()) {
                    entry<?, ?> entry = (entry)var6.next();
                    string factorytypename = ((string)entry.getkey()).trim();
                    string[] factoryimplementationnames = stringutils.commadelimitedlisttostringarray((string)entry.getvalue());
                    string[] var10 = factoryimplementationnames;
                    int var11 = factoryimplementationnames.length;

                    for(int var12 = 0; var12 < var11; ++var12) {
                        string factoryimplementationname = var10[var12];
                        ((list)result.computeifabsent(factorytypename, (key) -> {
                            return new arraylist();
                        })).add(factoryimplementationname.trim());
                    }
                }
            }

            result.replaceall((factorytype, implementations) -> {
                return (list)implementations.stream().distinct().collect(collectors.collectingandthen(collectors.tolist(), collections::unmodifiablelist));
            });
            cache.put(classloader, result);
            return result;
        } catch (ioexception var14) {
            throw new illegalargumentexception("unable to load factories from location [meta-inf/spring.factories]", var14);
        }
    }
}

meta-inf/spring.factories

主启动类

@springbootapplication
public class springboot01application {
    //将springboot应用启动,该方法返回一个configurableapplicationcontext对象
    //参数一:应用入口的类,参数二:命令行参数
    public static void main(string[] args) {
        springapplication.run(springboot01application.class, args);
    }
}

springapplication 类的实例化

这个类主要做一下四件事

run 方法的执行

springapplication.run 做了什么?

springapplication.run 一共做了两件事,

一件是创建 springapplication 对象,在该对象初始化时,找到配置的事件监听器,并保存起来。

第二件事就是运行 run 方法,此时会将刚才保存的事件监听器根据当前时机触发不同的事件,比如容器初始化,容器创建完成等。同时也会刷新 ioc 容器,进行组件的扫描、创建、加载等工作

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

赞 (0)

您想发表意见!!点此发布评论

推荐阅读

Java后台如何查询并返回树形结构数据给前端

10-11

SpringBoot自动装配底层原理是什么?自定义自动装配实战教程

10-11

SpringBoot整合MyBatis完整教程,如何实现登录注册功能

10-11

Spring Cloud Alibaba Sentinel控制台使用解读

10-11

Spring AI拦截器实现RAG检索的两种方式

10-11

Spring Security自定义退出登录配置实战教程

10-11

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论