#|Spring Boot spring.factories 用法及原理


文章目录

        • 1. spring.factories 用法
        • 2. spring.factories 实现原理
        • 3. spring.factories 用于解决什么问题?
          • 3.1 业务场景思考及 starter 机制引入
          • 3.2 Spring Boot starter 机制
        • 4. 小结

近期看到业务代码里用到 spring.factories 的配置,觉得场景不合适,且网上少有文章提及 spring.factories 与 starter 机制的前因后果,本文借此机会理一下 spring.factories 的用法及原理。简单地说, Spring Boot 的 spring.factories 配置机制类似于 Java SPI,工程代码中在 META-INF/spring.factories 文件中配置接口的实现类名称,然后 Spring Boot 在启动时扫描该配置文件并实例化配置文件中的Bean。 详细看下面用法:
1. spring.factories 用法
  • Spring Boot 启动类 MainApplication
package com.zqh.test.springfactories; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author fangchen * @date 2022-02-19 14:18 */ @SpringBootApplication public class MainApplication {public static void main(String[] args) { SpringApplication.run(MainApplication.class, args); } }

  • META-INF/ spring.factories 配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zqh.test.springfactories.TestBean

  • TestBean.class 测试Bean
package com.zqh.test.springfactories; /** * @author fangchen * @date 2022-02-19 14:16 */ public class TestBean {private Long id; public TestBean() { System.out.println("test bean init....."); }public Long getId() { return id; }public void setId(Long id) { this.id = id; } }

  • pom.xm maven 依赖
4.0.0com.zqh.test springBootDemo 1.0-SNAPSHOT org.springframework.boot spring-boot-starter 2.6.3

运行 MainApplication 类,结果如下,从中可以看出 TestBean 类已经在Spring Boot 启动时已经进行实例化。
2022-02-19 19:49:30.274INFO 20112 --- [main] c.z.t.springfactories.MainApplication: Starting MainApplication using Java 1.8.0_221 on DESKTOP-ITB0Q9I with PID 20112 (D:\code\springBootDemo\target\classes started by NINGMEI in D:\code\springBootDemo) 2022-02-19 19:49:30.276INFO 20112 --- [main] c.z.t.springfactories.MainApplication: No active profile set, falling back to default profiles: default test bean init..... 2022-02-19 19:49:30.614INFO 20112 --- [main] c.z.t.springfactories.MainApplication: Started MainApplication in 0.595 seconds (JVM running for 0.864)

2. spring.factories 实现原理 Spring Boot 启动时先读取 spring.factories 的类列表,然后再一个个实例化,并放到 Spring 上下文中。代码比较简单,不再详述,直接看图。
  • 源码类:org.springframework.core.io.support.SpringFactoriesLoader(spring-core包)
    #|Spring Boot spring.factories 用法及原理
    文章图片
3. spring.factories 用于解决什么问题? 在日常开发中,通常将 Bean 注入到 Spring 容器有多种方式,比如 @Autowire、@Import 注解等等,又为什么使用 spring.factories 配置机制呢?
个人理解:当应用依赖三方 jar 包时,spring.factories 配置方式可以使三方 jar 包中的 bean 有选择地注入到 Spring 容器中。 下面以 Spring Boot 的 starter 机制来说明怎么使用 spring.factories 配置文件的。
3.1 业务场景思考及 starter 机制引入 先思考一个场景:应用需要依赖 RedisTemplate 进行缓存操作,怎么引入配置呢? 一般有两种方式:
  • 方式一:将依赖的 RedisTemplate 等相关 Bean 手动一个一个分散注入到业务应用中(比如@Autowire、@Configuration等)
  • 方式二:将依赖的 RedisTemplate 等相关 Bean 统一引入到一个配置类中,并标记为 @Configuration
第一种方式明显不可取,即耦合了业务,而且后续包升级比较麻烦。第二种统一的做法比较推荐,非常易于管理。假如采用方法二将这个标记为 @Configuration 类命名为 RedisAutoConfiguration,则这个类就封装了引入 redis 必须要注入 Spring 的 Bean,以此类推,后续再引入 mysql 时再将 mysql 必须依赖的类统一封装为 DataSourceAutoConfiguration 就可以了。恰好这正是 Spring Boot starter 机制内部的原理,即 Spring Boot starter将各个组件分别统一封装一个固定配置类中,如 redis 相关依赖类统一封装到 RedisAutoConfiguration 类中,数据库依赖类统一封装到 DataSourceAutoConfiguration 类等,然后将这些统一配置类配置到 spring.factories 文件中,Spring Boot在启动的时候(前提配置EnableAutoConfiguration注解,这也是EnableAutoConfiguration注解的由来)会一一扫描依赖 jar 包中 spring.factories 文件,最后将这些类注入到spring 容器中,业务直接引用即可。
#|Spring Boot spring.factories 用法及原理
文章图片

3.2 Spring Boot starter 机制 理解了上面,Spring Boot starter 机制的原理和定义就比较清晰了。再理解一下下面这段话:springboot starter 是一种插件机制,抛弃了之前繁琐的配置,将复杂依赖统一集成进 starter。starter 的出现极大的帮助开发者们从繁琐的框架配置中解放出来,从而更专注于业务代码,并且 springboot 官方提供除了企业级项目不同场景的 starter 依赖模块,可以很便捷的集成进项目,比如 springboot 项目需要依赖 redis,我们只需要加入 spring-boot-starter-data-redis 依赖,并配置一些必须的连接信息即可以使用。
4. 小结 从 Spring Boot starter 机制的原理来理解 spring.factories 配置似乎更好理解一些,至于为了实现 Spring Boot starter 机制才引入 spring.factories 配置,还是先有 spring.factories 配置才有 Spring Boot starter 机制的取巧,那就不得而知了。总之,spring.factories 配置为 Spring Boot 的自动装配提供了方便,在此基础上产生的 Spring Boot starter 机制为很多中间件开发带来了方便。
【#|Spring Boot spring.factories 用法及原理】欢迎如转载,请注明出处!欢迎关注微信公众号:方辰的博客

    推荐阅读