
在最开始我对 SPI 的理解就停留在“接口和实现解耦接口在调用方实现在服务方具体实现类写在META-INF/services/文件里。这只是一个静态的、用来应付面试的定义。只是知道它是这个而已除了这段话其他什么都不知道。但是要确认这个定义其实是百分百正确的并且我认为spi机制最大的价值就在于扩展性。我开始深入的去了解一下它才理解 SPI 这种“把所有实现类都加载出来”的方式有多么原始。一个典型的例子就是 JDBC 驱动。Java 定义了java.sql.Driver接口各个数据库厂商MySQL、PostgreSQL等去实现它然后把实现类写在自己的 SPI 配置文件里。当ServiceLoader加载时它会一次性把 classpath 下找到的所有数据库驱动实现都加载进内存不管你的项目到底用不用这一点也不优雅和智能。理解了“全量加载”的弊端我才真正领会到 Spring Boot 自动配置的强大之处。我以前只知道 Spring Boot 有个spring.factories文件和 SPI 很像。后来才想明白Spring Boot 的自动配置其实就是 SPI 思想的超级升级版。它同样是为了解耦业务和配置解耦同样有配置文件spring.factories但它加载配置类时不会傻乎乎地把所有东西都初始化。它会通过一系列Conditional注解比如ConditionalOnClass、ConditionalOnMissingBean进行按需加载。只有当你真的引入了某个依赖比如引入了spring-boot-starter-web对应的自动配置才会生效。这简直是一种从“手动的服务发现”到“智能的条件驱动”的质变。所以我对 SPI 的理解总结为SPI 的核心思想是“接口和实现解耦”。Java 原生 SPI 实现了基础的服务发现但比较粗暴而 Spring Boot 的自动配置通过条件注解实现了按需加载把 SPI 的扩展性思想真正做到了智能和优雅。总结其实我写这篇文章的时候还有很多东西我自己也讲不清楚。比如SPI 和类加载器有什么关系自己怎么设计一个 SPI 风格的组件如果你和我一样处于“好像懂了又好像没懂”的阶段别着急。多写几个项目多踩几个坑回头再看这些技术就会发现它们不再是冷冰冰的 API而是活生生的、为了解决某个问题而想出来的方案。