设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间20 现在时间20 缓存数据 和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

查看: 622|回复: 2

spring.factories文件的解析源码API机制详解

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
48
主题
38
精华
0
金钱
134
积分
86
注册时间
2023-9-30
最后登录
2025-9-25

发表于 2024-11-21 21:59:25 | 显示全部楼层 |阅读模式
目录
  • 引言
  • 一、Spring Boot的背景历史
    • 1.1 Spring Boot的起源与发展
    • 1.2 Spring Boot的核心特点
  • 二、Spring Boot的业务场景与功能点
    • 2.1 业务场景
    • 2.2 功能点
  • 三、Spring Boot的底层原理
    • 3.1 自动配置原理
    • 3.2 spring.factories文件解析源码API机制
      • 3.2.1 spring.factories文件的结构
      • 3.2.2 SpringFactoriesLoader类的解析机制
    • 3.3 内嵌服务器的实现原理
    • 四、手写模拟Spring Boot的启动过程
      • 4.1 定义注解和配置类
        • 4.2 创建SpringApplication类
          • 4.3 创建启动类
            • 4.4 模拟spring.factories文件的解析
            • 五、结论

              引言

              Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是

              1. spring.factories
              复制代码
              文件的解析源码API机制。

              一、Spring Boot的背景历史

              1.1 Spring Boot的起源与发展

              Spring Boot是由Pivotal团队开发的一个框架,它基于Spring框架,旨在简化Spring应用的开发和部署。Spring Boot最早于2014年发布,其设计初衷是为了应对复杂的企业级应用开发中频繁出现的配置冗余和重复代码问题。

              Spring Boot的发展历程可以分为几个关键阶段:

              • 早期发展(2013-2014年):Spring Boot开始开发,2014年4月发布了1.0.0版本,引入了核心特性如自动配置、起步依赖和命令行界面(CLI)。
              • 快速发展(2015-2017年):Spring Boot发布了多个版本,不断引入新功能和改进,如对Actuator的增强、更好的测试支持等,逐渐成为Java开发领域的热门框架。
              • 成熟与广泛应用(2018年至今):Spring Boot不断进行小版本的更新和改进,适应不断变化的技术需求,在云原生应用开发、容器化部署等方面发挥着重要作用。

              1.2 Spring Boot的核心特点

              Spring Boot的核心特点可以概括为以下几点:

              • 自动配置:根据类路径中的依赖和环境,自动配置Spring应用程序,减少手动配置的工作量。
              • 起步依赖:提供一系列的起步依赖,简化项目中的依赖管理。
              • 内嵌服务器:内置Tomcat、Jetty或Undertow等服务器,应用可以直接运行,无需外部服务器。
              • 生产就绪:提供监控、健康检查、外部配置等功能,使应用能够在生产环境中平稳运行。

              二、Spring Boot的业务场景与功能点

              2.1 业务场景

              Spring Boot适用于多种业务场景,包括但不限于:

              • 微服务架构:Spring Boot可以快速创建独立的、可独立部署的微服务应用程序。
              • RESTful API开发:提供丰富的支持和简化开发RESTful API的工具和功能。
              • Web应用程序开发:支持开发各种Web应用程序,如单页应用程序、多页应用程序、网站等。
              • 批处理应用程序:提供对批处理应用程序的支持,包括任务调度、处理大数据量、事务管理等。
              • 数据访问:简化与数据库和其他数据源的集成,通过自动配置和起步依赖简化数据访问层的开发。

              2.2 功能点

              Spring Boot的功能点非常丰富,以下是一些关键功能点:

              • 自动配置:根据classpath下的依赖和配置文件的内容,自动为应用程序进行配置。
              • 起步依赖:提供一系列的起步依赖,用于快速引入常见的第三方库和框架。
              • 内嵌服务器:内置Tomcat、Jetty、Undertow等多个服务器,开发者可以将应用程序打包成可执行的JAR或WAR文件,直接运行。
              • 监控和管理:提供了一些监控和管理的工具,如Actuator模块,帮助开发人员实时监控和管理应用程序的运行状态。
              • 外部化配置:支持外部化配置,可以通过配置文件、环境变量等方式灵活地配置应用程序。

              三、Spring Boot的底层原理

              3.1 自动配置原理

              Spring Boot的自动配置机制是其核心特性之一。它通过

              1. @EnableAutoConfiguration
              复制代码
              注解实现,根据类路径中的依赖自动配置合适的Spring组件。自动配置的实现主要依赖于
              1. SpringFactoriesLoader
              复制代码
              类和
              1. @EnableAutoConfiguration
              复制代码
              注解。

              在Spring Boot启动时,

              1. SpringFactoriesLoader
              复制代码
              会扫描类路径下的
              1. META-INF/spring.factories
              复制代码
              文件,加载其中定义的自动配置类。每个自动配置类都会根据一定的条件(如类路径中是否存在特定的类或Bean)来决定是否生效。

              3.2 spring.factories文件解析源码API机制

              1. spring.factories
              复制代码
              文件是Spring Boot自动配置机制的关键组成部分。它位于类路径下的
              1. META-INF
              复制代码
              目录中,用于定义Spring Boot的自动配置类和其他扩展点。

              3.2.1 spring.factories文件的结构

              1. spring.factories
              复制代码
              文件是一个简单的属性文件,其结构如下:

              1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
              2. com.example.autoconfigure.MyAutoConfiguration
              复制代码

              每一行定义了一个扩展点的接口名称和对应的实现类名称,多个实现类之间用逗号分隔。

              3.2.2 SpringFactoriesLoader类的解析机制

              1. SpringFactoriesLoader
              复制代码
              类是Spring Boot用于加载
              1. spring.factories
              复制代码
              文件中定义的类的工具类。其主要方法
              1. loadFactories
              复制代码
              用于加载指定接口的所有实现类:

              1. public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
              2. String factoryClassName = factoryClass.getName();
              3. try {
              4. Enumeration<URL> urls = (classLoader != null ? classLoader.getResources("META-INF/spring.factories") :
              5. ClassLoader.getSystemResources("META-INF/spring.factories"));
              6. List<String> factoryNames = new ArrayList<>();
              7. while (urls.hasMoreElements()) {
              8. URL url = urls.nextElement();
              9. Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
              10. String factoryNamesProperty = properties.getProperty(factoryClassName);
              11. for (String factoryName : StringUtils.commaDelimitedListToStringArray(factoryNamesProperty)) {
              12. factoryNames.add(factoryName.trim());
              13. }
              14. }
              15. return instantiateFactories(factoryClass, factoryNames, classLoader);
              16. }
              17. catch (IOException ex) {
              18. throw new IllegalArgumentException("Unable to load factories from location [" +
              19. "META-INF/spring.factories"]", ex);
              20. }
              21. }
              复制代码

              该方法首先通过

              1. classLoader.getResources
              复制代码
              方法找到所有
              1. META-INF/spring.factories
              复制代码
              文件的URL,然后逐个加载这些文件的内容,解析出指定接口的所有实现类名称,最后通过反射创建这些类的实例并返回。

              3.3 内嵌服务器的实现原理

              Spring Boot内置了Tomcat、Jetty或Undertow等服务器,使应用可以直接运行在这些服务器上,无需外部容器。内嵌服务器的实现原理主要包括以下几个步骤:

              • 选择服务器:根据项目的依赖和配置,选择使用哪种内嵌服务器。例如,如果项目中包含了
                1. spring-boot-starter-web
                复制代码
                依赖,则默认使用Tomcat服务器。
              • 配置服务器:通过配置文件或Java配置类,设置服务器的端口号、上下文路径、Session超时时间等属性。
              • 启动服务器:在应用启动时,创建并启动内嵌服务器。Spring Boot通过
                1. EmbeddedServletContainerFactory
                复制代码
                接口及其实现类来管理内嵌服务器的创建和启动过程。

              四、手写模拟Spring Boot的启动过程

              为了更深入地理解Spring Boot的启动过程,我们可以通过Java代码手写模拟Spring Boot的启动过程。以下是一个简单的模拟实现:

              4.1 定义注解和配置类

              首先,我们定义一个自定义的注解

              1. @ZhouyuSpringBootApplication
              复制代码
              ,用于标识Spring Boot应用的启动类:

              1. import org.springframework.boot.autoconfigure.SpringBootApplication;
              2. @SpringBootApplication
              3. public @interface ZhouyuSpringBootApplication {
              4. }
              复制代码

              然后,我们定义一个配置类

              1. WebConfig
              复制代码
              ,用于配置Spring MVC和视图解析器:

              1. import org.springframework.context.annotation.Bean;
              2. import org.springframework.context.annotation.ComponentScan;
              3. import org.springframework.context.annotation.Configuration;
              4. import org.springframework.web.servlet.ViewResolver;
              5. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
              6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
              7. import org.springframework.web.servlet.view.InternalResourceViewResolver;
              8. @Configuration
              9. @EnableWebMvc
              10. @ComponentScan(basePackages = "com.example.controller")
              11. public class WebConfig implements WebMvcConfigurer {
              12. @Bean
              13. public ViewResolver viewResolver() {
              14. InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
              15. viewResolver.setPrefix("/WEB-INF/views/");
              16. viewResolver.setSuffix(".jsp");
              17. return viewResolver;
              18. }
              19. }
              复制代码

              4.2 创建SpringApplication类

              接下来,我们创建一个自定义的

              1. SpringApplication
              复制代码
              类,用于启动Spring Boot应用:

              1. import org.springframework.boot.SpringApplication;
              2. import org.springframework.boot.autoconfigure.SpringBootApplication;
              3. import org.springframework.context.ConfigurableApplicationContext;
              4. public class ZhouyuSpringApplication {
              5. public static void run(Class<?> primarySource, String... args) {
              6. ConfigurableApplicationContext context = SpringApplication.run(primarySource, args);
              7. context.close();
              8. }
              9. }
              复制代码

              4.3 创建启动类

              最后,我们创建一个启动类

              1. MyApp
              复制代码
              ,并使用
              1. @ZhouyuSpringBootApplication
              复制代码
              注解进行标注:

              1. import com.example.config.WebConfig;
              2. import com.example.boot.ZhouyuSpringBootApplication;
              3. @ZhouyuSpringBootApplication
              4. public class MyApp {
              5. public static void main(String[] args) {
              6. ZhouyuSpringApplication.run(MyApp.class, args);
              7. }
              8. }
              复制代码

              4.4 模拟spring.factories文件的解析

              为了模拟

              1. spring.factories
              复制代码
              文件的解析过程,我们可以创建一个工具类
              1. SpringFactoriesLoader
              复制代码
              ,用于加载指定接口的所有实现类:

              1. import java.io.IOException;
              2. import java.io.InputStream;
              3. import java.util.ArrayList;
              4. import java.util.Enumeration;
              5. import java.util.List;
              6. import java.util.Properties;
              7. public class SpringFactoriesLoader {
              8. public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) throws IOException {
              9. String factoryClassName = factoryClass.getName();
              10. List<String> factoryNames = new ArrayList<>();
              11. Enumeration<URL> urls = classLoader.getResources("META-INF/spring.factories");
              12. while (urls.hasMoreElements()) {
              13. URL url = urls.nextElement();
              14. try (InputStream is = url.openStream()) {
              15. Properties properties = new Properties();
              16. properties.load(is);
              17. String factoryNamesProperty = properties.getProperty(factoryClassName);
              18. for (String factoryName : factoryNamesProperty.split(",")) {
              19. factoryNames.add(factoryName.trim());
              20. }
              21. }
              22. }
              23. List<T> factories = new ArrayList<>();
              24. for (String factoryName : factoryNames) {
              25. try {
              26. Class<?> factoryClass = Class.forName(factoryName, true, classLoader);
              27. T factory = (T) factoryClass.getDeclaredConstructor().newInstance();
              28. factories.add(factory);
              29. } catch (Exception e) {
              30. throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryName, e);
              31. }
              32. }
              33. return factories;
              34. }
              35. }
              复制代码

              然后,我们可以在启动类中使用这个工具类来加载并注册自动配置类:

              1. import com.example.config.WebConfig;
              2. import com.example.boot.ZhouyuSpringBootApplication;
              3. import org.springframework.context.annotation.ConfigurationClassPostProcessor;
              4. import java.util.List;
              5. @ZhouyuSpringBootApplication
              6. public class MyApp {
              7. public static void main(String[] args) throws IOException {
              8. List<ConfigurationClassPostProcessor> postProcessors = SpringFactoriesLoader.loadFactories(
              9. ConfigurationClassPostProcessor.class, MyApp.class.getClassLoader());
              10. // 注册自动配置类
              11. for (ConfigurationClassPostProcessor postProcessor : postProcessors) {
              12. // 这里可以添加逻辑来注册自动配置类
              13. }
              14. ZhouyuSpringApplication.run(MyApp.class, args);
              15. }
              16. }
              复制代码

              需要注意的是,上述代码只是一个简单的模拟实现,并没有完全覆盖Spring Boot的启动过程和自动配置机制的所有细节。在实际应用中,Spring Boot的启动过程和自动配置机制要复杂得多,涉及多个组件和类的协同工作。

              五、结论

              本文通过深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,使读者对Spring Boot有了更深入的了解。同时,通过手写模拟Spring Boot的启动过程,特别是

              1. spring.factories
              复制代码
              文件的解析源码API机制,使读者能够更直观地理解Spring Boot的自动配置机制。希望本文能够为读者在实际应用中更好地使用Spring Boot提供有益的参考和帮助。

              到此这篇关于spring.factories文件的解析源码API机制详解的文章就介绍到这了,更多相关spring.factories文件内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!


              免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
              晓枫资讯-科技资讯社区-免责声明
              免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
                    1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
                    2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
                    3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
                    4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
                    5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
              http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

                离线 

              TA的专栏

              等级头衔

              等級:晓枫资讯-列兵

              在线时间
              0 小时

              积分成就
              威望
              0
              贡献
              0
              主题
              0
              精华
              0
              金钱
              23
              积分
              26
              注册时间
              2022-12-26
              最后登录
              2022-12-26

              发表于 2025-1-21 06:52:21 | 显示全部楼层
              顶顶更健康!!!
              http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

                离线 

              TA的专栏

              等级头衔

              等級:晓枫资讯-列兵

              在线时间
              0 小时

              积分成就
              威望
              0
              贡献
              0
              主题
              0
              精华
              0
              金钱
              11
              积分
              2
              注册时间
              2025-1-23
              最后登录
              2025-1-23

              发表于 2025-12-9 03:22:43 | 显示全部楼层
              路过,支持一下
              http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
              严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
              您需要登录后才可以回帖 登录 | 立即注册

              本版积分规则

              1楼
              2楼
              3楼

              手机版|晓枫资讯--科技资讯社区 本站已运行

              CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

              晓枫资讯--科技资讯社区

              本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

              如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

              Powered by Discuz! X3.5

              快速回复 返回顶部 返回列表