下面有一个网上的例子,我只是写一些项目结构的东西,这个在网上没找到。
这个是一个SPI服务jar包。只定义了Search接口,具体实现交给其他项目。Console类是含Main的测试类,不用理会。
其中,META-INF/searvices/com.study.Search种的内容为com.study.spi.DatabaseSearch。表明只要在项目中创建com.study.spi.DatabaseSearch类,就能由该类提供给search服务。当然,也可以配置为FileSearch,那么其他项目中就要有FileSearch类。
另外的项目,Search服务的实际提供项目。
虽然有DatabaseSearch和FileSearch,但以为jar中声明的是DatabaseSearch,所以由它提供服务。
网上有人说spi不能再本身项目中测试,是不对的。
这样的目录结构就能直接运行Console测试了。修改META-INF/searvices/com.study.Search中的内容就能由不同的类提供search服务。
原因需要查看源代码:
在ServiceLoader.$LazyIterator
PREFIX = “META-INF/services/”,
loader调用ServiceLoader.load()的类的Loader。所以了,只要META_INF在classpath下能找到,就能加载。
这是具体实例化服务类的操作。
下面是网上的例子:
假设有一个内容搜索系统,分为展示和搜索两个模块。展示和搜索基于接口编程。搜索的实现可能是基于文件系统的搜索,也可能是基于数据库的搜索。实例代码如下
Search.java: 搜索接口
Java代码
1. package search;
2.
3. import java.util.List;
4.
5. import definition.Doc;
6.
7. public interface Search {
8. List<Doc> search(String keyword);
9. }
FileSearch.java:文件系统的搜索实现
Java代码
1. package search;
2.
3. import java.util.List;
4.
5. import definition.Doc;
6.
7. public class FileSearch implements Search {
8.
9. @Override
10. public List<Doc> search(String keyword) {
11. System.out.println("now use file system search. keyword:" + keyword);
12. return null;
13. }
14.
15. }
DatabaseSearch.java
Java代码
1. package search;
2.
3. import java.util.List;
4.
5. import definition.Doc;
6.
7. public class DatabaseSearch implements Search {
8.
9. @Override
10. public List<Doc> search(String keyword) {
11. System.out.println("now use database search. keyword:" + keyword);
12. return null;
13. }
14.
15. }
SearchTest.java
Java代码
1. package search;
2.
3. import java.util.Iterator;
4. import java.util.ServiceLoader;
5.
6. public class SearchTest {
7.
8. public static void main(String[] args) {
9. ServiceLoader<Search> s = ServiceLoader.load(Search.class);
10. Iterator<Search> searchs = s.iterator();
11. if (searchs.hasNext()) {
12. Search curSearch = searchs.next();
13. curSearch.search("test");
14. }
15. }
16. }
最后创建在META-INF/searvices/search.Search文件。
当search.Search文件内容是”search.FileSearch”时,程序输出是:
now use file system search. keyword:test
当search.Search文件内容是”search.DatabaseSearch”时,程序输出是:
now use database search. keyword:test
可以看出SearchTest里没有任何和具体实现有关的代码,而是基于spi的机制去查找服务的实现。