這裏先說下SPI的一個概念,SPI英文爲Service Provider Interface單從字面能夠理解爲Service提供者接口,正如從SPI的名字去理解SPI就是Service提供者接口;我對SPI的定義:提供給服務提供廠商與擴展框架功能的開發者使用的接口。java
不少框架都使用了java的SPI機制,如JDBC4中的java.sql.Driver的SPI實現(mysql驅動、oracle驅動等)、common-logging的日誌接口實現、dubbo的擴展實現等等框架;mysql
當服務的提供者,提供了服務接口的一種實現以後,在jar包的META-INF/services/目錄裏同時建立一個以服務接口命名的文件。該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。
基於這樣一個約定就能很好的找到服務接口的實現類,而不須要再代碼裏制定。
JDK提供服務實現查找的一個工具類:java.util.ServiceLoader。spring
SpirngBoot 啓動的時候會去掃碼Jar包裏面的META-INF/spring.factories文件,以下圖sql
在SpringBoot啓動時會篩選出META-INF/spring.factories 文件中實現 ApplicationContextInitializer 與 ApplicationListener的類oracle
如Spring-boot 包中咱們能夠看到實現ApplicationContextInitializer 與ApplicationListener 的子類框架
如ServerPortInfoApplicationContextInitializer,實現ApplicationContextInitializer 的initialize方法,當Spring實例化bean的過程當中會調用initilize方法
簡單的說當咱們要寫一個SpringBoot使用的插件時,咱們只要編寫一個實現ApplicationContextInitializer 的子類,而且在resources/META-INF/spring.factories 編寫好規範,那麼Spring 啓動時就會調用咱們的子類的initialize方法。ide