1.概念
本质上是解决同一个接口多种实现(策略模式),使用者如何能够方便的选择哪一个实现类的问题
2. jdk spi
接口:
public interface SpiService {
void sayHello();
}
- 1.resource下新建包META-INF.services
- 2.包中新建文件:接口全路径名称:com.ucar.spi.service.SpiService
- 3.文件中写上想要选择的实现类全路径名称:
com.ucar.spi.service.RmiSpiServiceImpl
com.ucar.spi.service.RestSpiServiceImpl - 4.代码测试
ServiceLoader<SpiService> spiLoader = ServiceLoader.load(SpiService.class);
Iterator<SpiService> iteratorSpi = spiLoader.iterator();
while (iteratorSpi.hasNext()) {
SpiService spiService = iteratorSpi.next();
spiService.sayHello();
}
3. dubbo spi
3.1 凡是dubbo中接口上有@SPI标注的,都可以用做扩展
例:源码中RandomLoadBalance
@SPI(RandomLoadBalance.NAME)
public interface LoadBalance{
3.2 例:用LoadBalance做一个扩展
- 写两个实现类,实现接口LoadBalance
public class FirstLoadBalance implements LoadBalance {
/**
*
* @param invokers 所有provider的实现
* @param url
* @param invocation
* @param <T>
* @return
* @throws RpcException
*/
@Override
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException {
System.out.println("启动第一个");
//假如规则是固定使用第一个
return invokers.get(0);
}
}
public class LastLoadBalance implements LoadBalance {
/**
*
* @param invokers 所有provider的实现
* @param url
* @param invocation
* @param <T>
* @return
* @throws RpcException
*/
@Override
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException {
System.out.println("启动最后一个");
//固定使用第一个
return invokers.get(invokers.size()-1);
}
}
3.3 resource下新建包和文件(接口全包路径名)
- 包名:META-INF.dubbo
- 文件名:com.alibaba.dubbo.rpc.cluster.LoadBalance
3.4 文件中写入所有实现,key-value形式
first=com.ucar.loadbalance.FirstLoadBalance
last=com.ucar.loadbalance.LastLoadBalance
3.5 消费端使用
<dubbo:reference id="userService" interface="com.ucar.service.UserService" loadbalance="first" />
<dubbo:reference id="orderService" interface="com.ucar.service.OrderService" loadbalance="last" >
直接在标签中引用key就可以
4. jdk和dubbo实现spi区别
1.MATE-INF下的文件内容,jdk是实现类全包路径名,dubbo是key-value格式
2.使用时,jdk需要拿到所有方法使用,dubbo只需要引用key到标签中就可





网友评论