分布式RPC系统框架Dubbo-21Dubbo的内核解析-SPI机制

        所谓Dubbo的内核是指,Dubbo中所有功能都是基于内核完成的,都是由内核作为基础;dubbo的内核包含四部分,SPI、AOP、IOC与Compiler,后三部分的实现都基于SPI,所以说SPI是内核的内核;

1.1 JDK的SPI机制

        SPI,Service Provider Interface,服务提供者接口,是一种服务发现机制;

 

1.2 JDK的SPI规范

  • 接口名:可随意定义(符合命名约定)

  • 实现类名:可随意定义(约定为serviceInterfaceIMPL)

  • 提供者配置文件路径:其查找的目录为META-INF/service

  • 提供者配置文件名称:接口的全限定性类名,没有扩展名

  • 提供者配置文件内容:该接口的所有实现类的全限定性类名写入到该文件中,一个类名占一行

1.3 示例

(1)定义接口

public interface SomeService {
	void doSome();
}

(2)定义接口配置文件路径及文件

#文件内容
com.zxy.service.impl.OneServiceImpl
com.zxy.service.impl.TwoServiceImpl

 (3)定义两个实现类

public class OneServiceImpl implements SomeService{

	public void doSome() {
		// TODO Auto-generated method stub
		System.out.println("执行OneServiceImpl中的doSome()");
	}

}
public class TwoServiceImpl implements SomeService{

	public void doSome() {
		// TODO Auto-generated method stub
		System.out.println("执行TwoServiceImpl中的doSome()");
	}
}

(4)定义测试类

/**
 * 需要调用两个实现类的doSome()方法,并且实现类不出现在此
 * 
 */
public class SPITest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ServiceLoader<SomeService> loader = ServiceLoader.load(SomeService.class);
		Iterator<SomeService> iterator = loader.iterator();
		
		while(iterator.hasNext()) {
			//运行到此处是会加载具体接口的实现类
			SomeService service = iterator.next();
			service.doSome();
		}
		
	}

}

1.4 JDK-SPI的弊端

     当接口的实现类存在多个,而调用者只想调用其中某一个实现的时候,就出现了问题,JDK的SPI机制是必须将所有的实现类加载进来,然后做判断调用,但是所有的实现类已经全部实例化并且加载到了内存中;

2.Dubbo的SPI

Dubbo并未直接使用JDK的SPI,而是在其基础上进行了改进;

2.1 规范说明

  • 接口名:可以随意定义;

  • 实现类名:在接口名前添加一个用于表示自身功能的“标示前缀”字符串;

  • 提供者配置文件路径:依次查找目录为

    META-INF/dubbo/internal

    META-INF/dubbo

    META-INF/services

  • 提供者配置文件名称:接口的全限定性类名,无需扩展名;

  • 提供者配置文件内容:文件的内容为key=value形式,value为该接口的实现类的全限定类性名,key可以随意,规范约定一般为该实现类的“标示前缀”(首字母小写),一个类名占一行;

  • 提供者加载:ExtensionLoader类相当于JDK SPI中的ServiceLoader类,用于加载提供者配置文件中所有的实现类,并创建相应的实例;

    ExtensionLoader有type类型概念,其内部的getExtensionLoader静态方法,有一个type参数,用此方法获取的实例,只能获取传入参数类型的SPI,也就是不同的SPI接口有不同的ExtensionLoader实例,这就是微服务+插件的一种思想;

2.2 Dubbo的SPI示例

实现一个下单功能,其支付方式支持支付宝与微信两种,即要定义一个SPI接口,其存在两个扩展类;

(1)创建工程dubbospi导入dubbo依赖

<!-- dubbo依赖 --> 
	<dependency>
	    <groupId>org.apache.dubbo</groupId>
	    <artifactId>dubbo</artifactId>
	    <version>2.7.0</version>
	</dependency>

 

(2)定义Order接口

/**
 * SPI标签,设置默认为wechat微信支付
 */
@SPI("wechat")
public interface Order {
	String way();
}

(3)定义接口配置文件路径及文件

#dubbo允许多个key
wechat,wechatdetry,wechatproty=com.zxy.spi.extension.WeChatOrder
alipay=com.zxy.spi.extension.AlipayOrder

(4)定义实现类

public class AlipayOrder implements Order{

	public String way() {
		// TODO Auto-generated method stub
		System.out.println("---支付宝way()---");
		return "支付宝支付方式";
	}

}

 

public class WeChatOrder implements Order{

	public String way() {
		System.out.println("---微信way()---");
		return "微信支付方式";
	}

}

(5)定义测试类

public class OrderTest {

	public static void main(String[] args) {
		
		//获取SPI接口Order的扩展加载实例
		ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
		
		//获取指定名的扩展类
		Order alipay = loader.getExtension("alipay");
		System.out.println(alipay.way());
		
		Order wechat = loader.getExtension("wechat");
		System.out.println(wechat.way());
		
		Order wechatdetry = loader.getExtension("wechatdetry");
		System.out.println(wechatdetry.way());
		
		Order wechatproty = loader.getExtension("wechatproty");
		System.out.println(wechatproty.way());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值