下面有一個網上的例子,我只是寫一些項目結構的東西,這個在網上沒找到。
這個是一個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的機制去查找服務的實現。