当前位置: 代码网 > it编程>编程语言>Java > SpringBoot自动配置原理是什么?从启动器到spring.factories全解析

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

2026年10月11日 • Java •我要评论
pom.xml父工程pom < spring-boot-starter-parent < spring-boot-dependencies核心依赖在父工程 spring-boot-depe

pom.xml

父工程

  • pom < spring-boot-starter-parent < spring-boot-dependencies
  • 核心依赖在父工程 spring-boot-dependencies 中

启动器

  • spring boot 的启动场景
  • spring boot 会将所有的功能场景都变成一个个的启动器
  • 需要使用什么功能,添加对应的启动器即可
<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);
    }
}

注解

  • springboot 在启动时,从类路径下 meta-inf/spring.factories 获取指定的值
  • 将这些自动配置的类导入容器,自动配置就会生效,帮我们自动配置
  • 整合 javase,解决方案和自动配置的东西都在 spring-boot-autoconfigure-2.6.3.jar 这个包下
  • 会将所有需要导入的组件以类名的方式返回,这些组件会被添加到容器中
注解名称注解作用
@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() 方法

  • 标记了 enableautoconfiguration 注解的类
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() 方法

  • 获取所有的配置
  • 从 meta-inf/spring.factories 中读取配置文件,封装成 properties,遍历 properties 供我们使用
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 类的实例化

这个类主要做一下四件事

  • 推断应用的类型是普通的项目还是 web 项目
  • 查找并加载所有可用初始化器,设置到 initializers 属性中
  • 找出所有的应用程序监听器,设置到 linsteners 属性中
  • 推断并设置 main 方法的定义类,找到运行的主类

run 方法的执行

  • 准备spring的上下文
  • 完成容器的初始化,创建,加载等
  • 在不同的时机触发监听器的不同事件

springapplication.run 做了什么?

springapplication.run 一共做了两件事,

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

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

总结

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

赞 (0)

相关文章:

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

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com