1、今天在学习java的spi思想时,自己动手写了一个demo,发现怎么也找不到spi的实现类,代码如下:
package com.fwkily.spi;
public interface Search {
void search();
}
package com.fwkily.spi;
public class ElasticSearch implements Search {
@Override
public void search() {
System.out.println("通过elasticsearch搜索!");
}
}
package com.fwkily.spi;
public class MysqlSearch implements Search {
@Override
public void search() {
System.out.println("通过mysql搜索!");
}
}
测试类:
package com.fwkily.spi;
import java.util.Iterator;
import java.util.ServiceLoader;
public class Main {
public static void main(String[] args) {
ServiceLoader<Search> loader = ServiceLoader.load(Search.class);
Iterator<Search> iterator = loader.iterator();
while (iterator.hasNext()){
iterator.next().search();
}
}
}
com.fwkily.spi.Search文件中写入该接口的实现类:
com.fwkily.spi.MysqlSearch
目录结构:
然而发现main方法怎么也打印不出实现类中的信息。
检查一下才发现META-INF/services目录需要放在classpath下面,将META-INF/services放入resources目录就好了,所以修改目录结构如下即可
再次运行成功:
chatgpt回答如下:
如果找不到SPI的实现类,有以下几种可能的解决方案:
-
检查classpath是否正确:在使用SPI时,需要将实现类的jar包放在classpath中,否则就会找不到对应的实现类。
-
检查META-INF/services目录是否正确:在使用SPI时,实现类需要在META-INF/services目录下创建一个以接口全限定名为命名的文件,文件中每行写入一个实现类的全限定名。如果实现类没有正确地放置在该文件中,也会导致找不到实现类。需要注意,该文件必须是UTF-8编码,并且不能有BOM头。
-
检查实现类的命名规则:在使用SPI时,实现类的命名规则要求以接口名为前缀,并且必须是public和无参构造函数。
-
检查实现类是否在特定的位置:某些框架或库可能会指定实现类必须放置在特定的位置下,例如Spring Boot会默认扫描
org.springframework.boot.autoconfigure.EnableAutoConfiguration
路径下的实现类。