首页 > 其他分享 >springboot 自动配置原理

springboot 自动配置原理

时间:2024-08-02 20:16:43浏览次数:6  
标签:return springboot 配置 annotationMetadata 自动 result 原理 加载 configurations

@SpringBootApplication》@EnableAutoConfiguration》@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector.java

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
            .loadMetadata(this.beanClassLoader);

        // 获取自动配置的实体
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
                                                                                  annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }


    /**
    具体用来加载自动配置类的方法
    */
    protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
                                                               AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        // 获取候选的配置类,即使后宫佳丽三千,也是要筛选的
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        // 根据情况,自动配置需要的配置类和不需要的配置了
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        // 返回最终需要的配置
        //@Param1:用来存储需要的配置项
        //@Param2:用来存储排除的配置项
        return new AutoConfigurationEntry(configurations, exclusions);
    }
}

/**
获取候选配置类【最重要!!!!!】
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                                                                         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;
}

/**
getCandidateConfigurations候选配置类 辅助方法
*/
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    // 返回的是EnableAutoConfiguration字节码对象
    return EnableAutoConfiguration.class;
}

/**
getCandidateConfigurations候选配置类 辅助方法
*/
protected ClassLoader getBeanClassLoader() {
    // 是一个类加载器
    return this.beanClassLoader;
}

/**
getAutoConfigurationEntry具体用来加载自动配置类的方法 辅助方法
*/
protected static class AutoConfigurationEntry {
    // 用来存储需要的配置项
    private final List<String> configurations;
    // 用来存储排除的配置项
    private final Set<String> exclusions;
}

SpringFactoriesLoader.java

//加载配置文件的路径: 
//也就是项目启动的时候会去加载所有 META-INF 下的所有的 spring.factories 文件
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

/**
这个方法就是根据刚才的字节码文件和类加载器来找到候选的配置类。
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    //获取的EnableAutoConfiguration.class的全限定名
    //org.springframework.boot.autoconfigure.EnableAutoConfiguration
    String factoryTypeName = factoryType.getName();
    return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

/**
通过loadSpringFactories()来获取到所有的配置类
*/
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    // 缓存加载的配置类
    MultiValueMap<String, String> result = cache.get(classLoader);
    if (result != null) {
        return result;
    }

    try {
        Enumeration<URL> urls = (classLoader != null ?
                                  // 去资源目录下找
                                 classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                                 ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
        result = new LinkedMultiValueMap<>();
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            UrlResource resource = new UrlResource(url);
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            for (Map.Entry<?, ?> entry : properties.entrySet()) {
                String factoryTypeName = ((String) entry.getKey()).trim();
                for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                    result.add(factoryTypeName, factoryImplementationName.trim());
                }
            }
        }
        // 加载完成放到缓存中
        cache.put(classLoader, result);
         // 返回加载到的配置类
        return result;
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Unable to load factories from location [" +
                                           FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
}

springboot自动配置加载的文件路径

springboot自动配置原理

标签:return,springboot,配置,annotationMetadata,自动,result,原理,加载,configurations
From: https://www.cnblogs.com/goodluckxiaotuanzi/p/18339419

相关文章

  • Spark内存计算引擎原理与代码实例讲解
    Spark内存计算引擎原理与代码实例讲解关键词:Spark,内存计算,RDD,DAG,Shuffle,容错,分布式计算1.背景介绍1.1问题的由来随着大数据时代的到来,传统的基于磁盘的MapReduce计算框架已经无法满足实时计算、迭代计算等场景对计算性能的要求。Spark应运而生,其基于内......
  • ElasticSearch分布式搜索引擎原理与代码实例讲解
    ElasticSearch分布式搜索引擎原理与代码实例讲解1.背景介绍1.1问题的由来在当今的数字时代,海量的数据被不断产生和存储。如何高效地检索和管理这些庞大的数据集成为了一个关键挑战。传统的关系型数据库虽然在事务处理和数据一致性方面表现出色,但在处理非结构化数据和......
  • Springboot 计算机毕业设计“爱艺创”特长培训管理系统程序
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,教职工,班级信息,课程分类,课程信息,风采展示,学生档案,教职工档案开题报告内容一、研究背景与意义1.研究背景随着社会的发展和进步,特长培训在培养学......
  • Springboot计算机毕业设计“漫画之家”系统+程序+源码
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,漫画,同人插画,漫画活动,商品,约稿,约稿公告开题报告内容一、选题的背景及意义1.1背景随着科学技术的飞速发展和互联网的普及,漫画作为一种独特的艺术......
  • Springboot计算机毕业设计《C语言程序设计》题库管理系统39b5j
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,教师,课程章节,课程信息,考点信息开题报告内容一、选题背景及意义随着计算机技术的快速发展,C语言作为一种基础且功能强大的高级程序设计语言,在操作系统......
  • Selenium + Python 自动化测试01(准备篇)
        本篇文章主要讲述Selenium+Python自动化测试-准备篇。主要时相关软件介绍,下载,安卓等。一、Selenium简介    1、Selenium是什么?        官网描述:        Primarily,itisforautomatingwebapplicationsfortestingpurposes,......
  • CentOS 8 和 Ubuntu 20.04.2 LTS 中,您可以通过不同的方法实现在系统启动时自动运行特
    在CentOS8和Ubuntu20.04.2LTS中,您可以通过不同的方法实现在系统启动时自动运行特定指令或脚本。这里是关于两种方法的解释和区别:###方法一:使用`rc-local.service`**CentOS8示例:** $cat/etc/rc.local_my.sh#!/bin/bash/bin/bash-c"ip-6routeadddefaultvi......
  • springboot+vue前后端分离项目-项目搭建15-集成JWT token权限验证
    1.对之前的代码改造,之前将user存储到sessionStorage,改成存储到localStorage,全局搜索修改 之前Result.code等于0代表success,改成200代表success,vue文件全局搜索修改一、前端部分1.改造request.js,登录时将user已经存储到localStorage里,这里将user获取到,将user里的token放到......
  • Applescrip成功实现FaceTime蓝号检测,检测是否开通FaceTime功能的实现原理
    FaceTime是苹果公司iOS和macOS(以前称MacOSX或OSX)内置的一款视频通话软件,通过Wi-Fi或者蜂窝数据接入互联网,在两个装有FaceTime的设备之间实现视频通话。其要求通话双方均具有装有FaceTime的苹果设备,苹果ID以及可接入互联网的3G/4G/5G或者Wi-Fi网络。一、Windows电脑上部署......
  • 不断自动搜索连接snap7
    我们想通过wifi自动连接PLC。当树莓派启动并自动运行他的程序时。它应该是一个独立的树莓派,所以我们没有键盘或任何东西。我们通过snap7发送数据。这可行,但如果wifi断开连接,我会收到此错误:“ISO:接收TCP期间发生错误:连接超时”有时在程序开始时我们会收到此错误:“Snap7Exc......