SPI META-INF/services/目录

package com.thfund.wuyy.test;

import java.util.Iterator;
import java.util.ServiceLoader;

import com.thfund.wuyy.intf.CacheDataSource;

public class CMain {

	public static void main (String[] args){
		
		ServiceLoader<CacheDataSource> s = ServiceLoader.load(CacheDataSource.class);
		Iterator<CacheDataSource>it = s.iterator();
		for (;it.hasNext();){
			CacheDataSource cacheDataSource = it.next();
			cacheDataSource.getDataSource();
		}
	}
}

上面是主线程的源码:

package com.thfund.wuyy.intf;

public interface CacheDataSource {

	String getDataSource();
}

此为SPI接口源码:

package com.thfund.wuyy.impl;

import com.thfund.wuyy.intf.CacheDataSource;

public class MemoryCacheDataSource implements CacheDataSource {

	@Override
	public String getDataSource() {
		// TODO Auto-generated method stub
		System.out.println(this.getClass().getClassLoader());
		System.out.println("MemoryCacheDataSource");
		return null;
	}

}

这是具体实现类的源码:

 

整个项目的目录结构:

com.thfund.wuyy.intf.CacheDataSource 文件的内容:com.thfund.wuyy.impl.MemoryCacheDataSource

 

编译命令:

javac -d bin src/com/thfund/wuyy/impl/*.java src/com/thfund/wuyy/intf/*.java src/com/thfund/wuyy/test/*.java

此处对比C++,C++用makfile编译需要自己编写每个文件之前的依赖关系,但明显javac 不用。这时非常方便的!

运行命令:

java.exe -Dfile.encoding=UTF-8 -classpath D:\workspace\Program\practice\selftest\SPITest\bin com.thfund.wuyy.test.CMain

 

第一个细节点(极其简单高手勿喷):

用编译命令编译完项目目录结构如下:

D:\workspace\Program\practice\selftest\SPITest>javac -d bin src/com/thfund/wuyy/impl/*.java src/com/thfund/wuyy/intf/*.java src/com/thfund/wuyy/test/*.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8

D:\workspace\Program\practice\selftest\SPITest>dir bin
 Volume in drive D is DATA
 Volume Serial Number is 526A-FE14

 Directory of D:\workspace\Program\practice\selftest\SPITest\bin

2018/11/21  16:47    <DIR>          .
2018/11/21  16:47    <DIR>          ..
2018/11/21  16:29    <DIR>          com
               0 File(s)              0 bytes
               3 Dir(s)  233,028,145,152 bytes free

D:\workspace\Program\practice\selftest\SPITest>

此时我们在META-INF/services 目录创建的文件还没有拷过来需要用命令拷贝一下,如果用eclipse 编译器,eclipse 会将src目录下所有的目录都拷贝到bin目录下。

下面我们来看一下ServiceLoader.load 是怎么找到配置文件并通过配置文件中的类名加载类、执行。

首先看一下ServiceLoader类的一点代码

public final class ServiceLoader<S>
    implements Iterable<S>
{

    private static final String PREFIX = "META-INF/services/";

    // The class or interface representing the service being loaded
    private Class<S> service;
    
    /* 

    此处省略一万行
    */
}

我们看到ServiceLoader类写死了META-INF 目录,再来看一下我们的执行命令:

java.exe -Dfile.encoding=UTF-8 -classpath D:\workspace\Program\practice\selftest\SPITest\bin com.thfund.wuyy.test.CMain

ServiceLoader类会扫描所有classpath 目录中的META-INF/services/ 然后查找com.thfund.wuyy.intf.CacheDataSource文件中的类名称,然后创建。

加载函数如下:

public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return ServiceLoader.load(service, cl);
    }

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值