灵活的 SPI 机制!
使用SPI机制前后的代码变化
加载MySQL对JDBC的Driver接口实现
在未使用SPI机制之前,使用JDBC操作数据库的时候,一般会写如下的代码:
在使用了SPI机制之后,就直接可以调用// 通过这行代码手动加载MySql对Driver接口的实现类 Class.forName("com.mysql.jdbc.Driver") DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study", "root", "root");
DriverManager.getConnection()
方法获取连接了。SLF4J查找日志门面实现
在未使用SPI机制之前,SLF4J日志门面在查找具体的日志实现时,需要每个实现提供一个叫org.slf4j.com.impl.StaticLoggerBinder.class
类,这里其实就跟SPI机制有点类似了,这个类实现了和SPI机制中的配置文件的功能,通过这个类来实现和具体实现的绑定关系。使用了SPI机制之后则是通过
SLF4JServiceProvider
类来实现和具体实现的绑定关系。
SPI代码实现案例
假设现在有一个Plugin的接口,调用方通过PluginFactory
中的installPlugins
方法来加载实现实现类,并进行调用,代码如下所示:
// Plugin接口
public interface Plugin {
boolean install(Map<Object, Object> context);
}
public class PluginFactory {
public void installPlugins() {
Map<Object, Object> context = new HashMap<>();
context.put("_beans", new ArrayList<>());
context.put("_version", "1.0.0");
context.put("_aspects", new HashMap<>());
// 这里通过ServiceLoader加载Plugin的实现类
ServiceLoader<Plugin> loader = ServiceLoader.load(Plugin.class);
for (Plugin plugin : loader) {
plugin.install(context);
}
}
public static void main(String[] args) {
PluginFactory factory = new PluginFactory();
factory.installPlugins();
}
}
Plugin接口实现者的代码:
public class LogPlugin implements Plugin {
private static final Logger LOGGER = LogManager.getLogger();
@Override
public boolean install(Map<Object, Object> context) {
LOGGER.info("Login plugin is initiating...");
return true;
}
}
使用SPI机制有个好处就是:当需要切换不同的实现类时,无需对业务代码进行适配修改,直接将Maven配置里面的实现依赖切换即可,对于实际的环境可能就是直接将对应的jar包替换到对应的lib目录下,然后重启服务即可。
SPI代码实现原理
ServiceLoader的load方法实现原理是通过接口的全限定名称去读取META-INF/services
路径下的文件,获取文件里面实现类的全限定名,然后加载该类,并通过反射的方式调用构造器获取实现类的实例,然后返回,如下图所示:



作者:javadaydayup
出处:https://www.cnblogs.com/javadaydayup/p/18315062
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验