了解Spring的SPI机制
Java SPI
SPI 全称 Service Provider Interface ,是 Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件 。 SPI的作用就是为这些被扩展的API 寻找服务实现 。本质是通过基于接口的 编程+策略模式+配置文件 实现动态加载。可以实现 解耦 (接口和实现分离),提高框架的 可拓展性 (第三方可以自己实现,达到插拔式的效果)。
getRunListeners()方法
/**
* 获取SpringApplicationRunListeners实例,listeners属性为SpringApplicationRunListener集合
* @param args
* @return
*/
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 构造参数设置
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// TODO 前面获取过org.springframework.context.ApplicationListener,这里是
// 获取SpringApplicationRunListener.class工厂实例,转成集合,并设置初始化器到属性listeners中
// org.springframework.boot.SpringApplicationRunListener= \
/*
* 读取的时候会去重以及排序的
* spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories 1个
*/
return new SpringApplicationRunListeners(
logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class,
types,
this,
args));
}
getSpringFactoriesInstances()
/**
* 获取指定class路径对应配置的类集合,比如org.springframework.context.ApplicationContextInitializer
*
* SPI机制的实现
* 从配置文件中加载接口的实现类
*/
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 1.获取一个类加载器
ClassLoader classLoader = getClassLoader();
// 2.遍历jar包META-INF/spring.factories的资源文件开始读取喽
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 3.创建Spring工厂实例
// TODO parameterTypes为工厂创建的实例对应的构造方法的签名样子,比如几个参数,每个参数的类型
// TODO args为对应的构造参数的具体值
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 4.对Spring工厂实例排序(org.springframework.core.annotation.Order注解指定的顺序)
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
SpringApplicationRunListeners
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
//省略一下代码....
}
EventPublishingRunListener
/**
*
* 根据SpringBoot启动过程中不同阶段发布对应的事件
*/
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
//事件发布是通过下面这个多播器来实现发布的
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
}