这里先说下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