service provider framework是一個系統, 實現了SPI, 在系統里多個服務提供者模塊可以提供一個服務的實現, 系統讓客戶端可以使用這些實現, 從而實現解耦。
一個service provider framework有3個主要的組成部分:
- 一個服務接口, 供服務提供者實現。
- 一個注冊API, 系統使用這個API來注冊服務接口的實現, 從而讓客戶端使用。
- 一個service access API, 客戶端可以選擇獲取一個服務的實例。
Java SPI:
Service Provider Interface(SPI)是一個可以被第三方擴展或實現的API, 它可以用來實現框架擴展和可替換的模塊。
使用步驟:
- 服務調用方通過ServiceLoader.load加載服務接口的實現類實例
- 服務提供方實現服務接口后, 在自己Jar包的META-INF/services目錄下新建一個接口名全名的文件, 並將具體實現類全名寫入。
Spring SPI
很多開源庫中都直接或間接地使用了Java的SPI機制, 如Spring中就有類似的SPI機制, 通過SpringFactoriesLoader代替JDK中的ServiceLoader, 通過META-INF/spring.factories文件代替META-INF/service目錄下的描述文件, 原理都是使用了Java的反射機制。
Spring提供的SPI只需要且只有一個文件, 就是META-INF/spring.factories
Spring的SPi也更加靈活, 不必要key是接口, 值是實現類, 例如Spring boot使用這種方式來處理自動配置的bean: key是注解(如org.springframework.boot.autoconfig.EnableAutoConfiguration), 值是被標記@Configuration的類。
另外Spring中還有converter spi和formatter spi。
converter可以用做任意兩個類型之間的轉換, formatter spi用做string類型和其他類型之間的轉換。
Converter和Formatter接口即服務接口
ConersionService實現了ConverterRegistry接口, 提供服務實現的注冊, 同時也提供可訪問功能。
而FormattingConversionService
則實現了FormatterRegistry接口, 實現了formatter實現類的注冊和調用。 同時FormattingConversionService也實現了ConversionService接口。