持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
理解SPI机制
SPI机制:
Service Provider Interface,就是一种服务发现的机制
举个例子: 以前:我是甲方调用你乙方的接口,乙方给我接口,然后提供给我接口文档,我按照文档进行开发
现在有了SPI机制:甲方自己提供接口,我仅仅只是提供接口,不实现,我提供api,乙方根据我这个api,自己去实现,然后乙方把jar给甲方,甲方只要找到依赖就行了
调用逻辑:
1,甲方提供接口
2,乙方依赖接口所在的包,并且创建实现类实现该接口
3,在乙方实现类所在的jar包里面你要告诉甲方,实现类到底在哪里
在META-INF目录下创建一个services目录,在services目录下以接口的全路径名作为文件名,然后在文件里面写上所有实现类的全路径名
4,甲方依赖你乙方的jar包之后要进行调用ServiceLoader.load(SPIService.class)
load底层是一个迭代器
迭代:
核心代码:
这里就很明显了,这个PREFIX就是**META-INF/services/**
再利用反射机制,再实例化一下
SPI机制在SpringBoot中的体现
总结就是:
springboot启动,执行main方法里的run方法------>
扫描@SpringBootApplication这个注解,这个注解里带了个@Import注解------>
import注解里面有AutoConfigurationImportSelector类------>
这个类实现了DeferredImportSelector接口,DeferredImportSelector接口又实现了ImportSelector接口------>
这个接口里有个SelectImport方法,这个方法实现了配置类的寻找------>
寻找的过程实际上就是SpringBoot的SPI机制,去META-INF/spring.factories文件
上面的SPI样例里的ServiceLoader,到SpringBoot中就是SpringFactoryLoader
点进去就可以看到
也写死了
SpringBoot中的Spring
首先springboot是包含spring的
springboot的run方法里面有个refreshContext方法是spring的主要方法,这个方法就是spring,spring的所有流程都在这个方法里面(这个方法其他的东西是springboot的东西)
refresh方法的源码:
spring 最重要的12步
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//1
this.prepareRefresh();
//2
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//3
this.prepareBeanFactory(beanFactory);
try {
//4
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//5
this.invokeBeanFactoryPostProcessors(beanFactory);
//6
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//7
this.initMessageSource();
//8
this.initApplicationEventMulticaster();
//9
this.onRefresh();
//10
this.registerListeners();
//11
this.finishBeanFactoryInitialization(beanFactory);
//12
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
spring:
1.将类注册成BeanDefinition
两种方法:
1)xml文件,读然后解析,实现方法是obtain
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
2)注解
this.invokeBeanFactoryPostProcessors(beanFactory);
2.然后实例化
流程图:
spring spi和jdk spi的区别
springboot的多了个自动装配的key = EnableAutoConfiguration
补充:
Dubbo的spi最最最重要的区别就是用谁加载谁
四种方法,是先加载到容器中,然后用哪个实例化哪个