我的编程空间,编程开发者的网络收藏夹
学习永远不晚

springboot 加载 META-INF/spring.factories方式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

springboot 加载 META-INF/spring.factories方式

springboot 加载 META-INF/spring.factories

用户应用程序Application


ConfigurableApplicationContext context = SpringApplication.run(NacosSpringBootYamlApplication.class, args);

SpringApplication类


public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
  return run(new Class<?>[] { primarySource }, args);
 }

// 这里Class是数组
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
  return new SpringApplication(primarySources).run(args);
 }

public SpringApplication(Class<?>... primarySources) {
  this(null, primarySources);
 }

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  this.resourceLoader = resourceLoader;
  Assert.notNull(primarySources, "PrimarySources must not be null");
  this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 这里就是SpringMvcApplication的实例
  this.webApplicationType = WebApplicationType.deduceFromClasspath();// deduce(推断)web类型(servlet、reactive、NoWeb)
  setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 这里会处理加载所有的spring.factories文件的内容到缓存 找到*META-INF/spring.factories*中声明的所有ApplicationContextInitializer的实现类并将其实例化
  setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //找到*META-INF/spring.factories*中声明的所有ApplicationListener的实现类并将其实例化
  this.mainApplicationClass = deduceMainApplicationClass(); //获得当前执行main方法的类对象,这里就是SpringMvcApplication的实例
 }

具体加载该classLoader下的所有spring.factories到缓存

如果缓存已经存在,则直接根据key,返回数据



 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  MultiValueMap<String, String> result = cache.get(classLoader);
  if (result != null) { //已经处理过了  直接返回
   return result;
  }
//url: // file:/C:/Users/kongqi/.m2/repository/org/springframework/spring-beans/5.1.9.RELEASE/spring-beans-5.1.9.RELEASE.jar!/META-INF/spring.factories
  try { //得到classloader下的所有jar包中的spring.factories的文件
   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); // 得到spring.factories的内容
    for (Map.Entry<?, ?> entry : properties.entrySet()) { // key: spring.factories的key  value: spring.factories的value
     String factoryClassName = ((String) entry.getKey()).trim(); // spring.factories的key
     for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {//value根据逗号,分隔
      result.add(factoryClassName, factoryName.trim()); //factoryClassName其实就是spring.factories的key   由于value是List类型 MultiValueMap value有多个
     }
    }
   }
   cache.put(classLoader, result);
   return result;
  }
  catch (IOException ex) {
   throw new IllegalArgumentException("Unable to load factories from location [" +
     FACTORIES_RESOURCE_LOCATION + "]", ex);
  }
 }

流程图

建立META-INF/spring.factories文件的意义何在

平常我们如何将Bean注入到容器当中


@Configuration
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
    @Autowired
    HelloProperties helloProperties;
    @Bean
    public HelloService helloService() {
        HelloService service = new HelloService();
        service.setHelloProperties( helloProperties  );
        return service;
    }
}

一般就建立配置文件使用@Configuration,里面通过@Bean进行加载bean

或者使用@Compont注解在类上进行类的注入

注意:

在我们主程序入口的时候:

@SpringBootApplication这个注解里面的东西


@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) })
public @interface SpringBootApplication {

里面注解@EnableAutoConfiguration

@ComponentScan注解指扫描@SpringBootApplication注解的入口程序类所在的basepackage下的

所有带有@Component注解的bean,从而注入到容器当中。

但是

如果是加入maven坐标依赖的jar包,就是项目根目录以外的Bean是怎么添加的??

这个时候注解@EnableAutoConfiguration的作用就来了

导入了AutoConfigurationImportSelector这个类:

这个类里面有一个方法


    
    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;
    }

@EnableAutoConfiguration注解来注册项目包外的bean。而spring.factories文件,则是用来记录项目包外需要注册的bean类名

为什么需要spring.factories文件,

因为我们整个项目里面的入口文件只会扫描整个项目里面下的@Compont @Configuration等注解

但是如果我们是引用了其他jar包,而其他jar包只有@Bean或者@Compont等注解,是不会扫描到的。

除非你引入的jar包没有Bean加载到容器当中

所以我们是通过写/META-INF/spring.factories文件去进行加载的。

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

springboot 加载 META-INF/spring.factories方式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot spring.factories加载时机分析

这篇文章主要为大家介绍了SpringBoot spring.factories加载时机分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-13

SpringBoot spring.factories加载时机源码分析

这篇文章主要介绍“SpringBoot spring.factories加载时机源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringBoot spring.factories加载时机源
2023-07-05

SpringBoot加载bean的八种方式总结

springboot难免要用到bean,但这些bean如何导入,对于初学者时间头疼的事,下面这篇文章主要给大家介绍了关于SpringBoot加载bean的八种方式,需要的朋友可以参考下
2022-11-13

spring或者springboot调整bean加载顺序的方式

这篇文章主要介绍了spring或者springboot调整bean加载顺序的方式,本文通过实例代码讲解三种调整类加载顺序的方式,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-01

Idea springboot springCloud热加载热调试两种常用方式

这篇文章主要介绍了Idea springboot springCloud热加载热调试常用的两种方式,在项目开发的过程中,需要修改调试的时候偶每次都需要重启项目浪费时间,下面是我整理的两种常用的两种方式,需要的朋友可以参考下
2023-05-14

springboot怎么加载第三方包

Spring Boot使用Maven作为项目管理工具,可以通过在pom.xml文件中添加第三方包的依赖来加载。以下是加载第三方包的步骤:打开项目的pom.xml文件。在标签中添加依赖项。例如,要加载一个名为"example"的第三方包,可
2023-10-27

SpringBoot框架的MD5加密方式

这篇文章主要介绍了SpringBoot框架的MD5加密方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-22

SpringBoot下载文件的正确方式~

Spring Boot 配合 axios 实现文件下载功能 前言比较一般的解法分析原因 正确解法 前言 最近遇到一个奇怪的需求,前端通过post请求下载压缩文件,同时会传给后端一些数据,用于生成压缩包。此时后端接口就不仅仅是
2023-08-23

@ConfigurationProperties加载外部配置方式

这篇文章主要介绍了@ConfigurationProperties加载外部配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录