ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Dubbo源码阅读(二)-Dubbo SPI机制

2021-02-23 10:02:37  阅读:161  来源: 互联网

标签:Dubbo Protocol dubbo url SPI rpc 源码 apache org


一、Java原生 SPI

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。

1、使用

在扩展类的 jar 包内,放置扩展点配置文件 META-INF/services/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。

2、缺点:

a、接口的所有实现类全部都需要加载并实例化;
b、无法根据参数来指定实现类;
c、不能解决IOC、AOP的问题。

二、Dubbo SPI

1、使用

在扩展类的 jar 包内,放置扩展点配置文件 META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。

2、自适应拓展点:@Adaptive
package com.alibaba.dubbo.rpc;
 
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Adaptive;
import com.alibaba.dubbo.common.extension.SPI;
 
/**
 * Protocol. (API/SPI, Singleton, ThreadSafe)
 */
@SPI("dubbo")
public interface Protocol {
 
    int getDefaultPort();
    
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
 
    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
 
    void destroy();
 
}

@Adaptive称为自适应扩展点注解,在实际应用场景中,一个扩展接口往往会有多种实现类,因为Dubbo是基于URL驱动,所以在运行时,通过传入URL中的某些参数来动态控制具体实现,这便是Dubbo的扩展点自适应特性。

以上面的Protocol接口为例,我们发现里面有两个方法export和refer,该方法上被@Adaptive修饰。
在运行的时候会针对 Protocol 生成代理类Protocol $ Adaptive代理类Protocol$Adaptive的export和refer方法的代码会在运行的时候动态根据 url 中的 protocol 来获取那个 key,默认是 dubbo,你也可以自己指定,你如果指定了别的 key,那么就会获取别的实现类的实例了,这就有点AOP的味道了。
Protocol $ Adaptive

import org.apache.dubbo.common.extension.ExtensionLoader;
 
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
	public void destroy() {
		throw new UnsupportedOperationException(
				"The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
	}
 
	public int getDefaultPort() {
		throw new UnsupportedOperationException(
				"The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
	}
 
	public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0)
			throws org.apache.dubbo.rpc.RpcException {
		if (arg0 == null)
			throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
		if (arg0.getUrl() == null)
			throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
		org.apache.dubbo.common.URL url = arg0.getUrl();
		String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
		if (extName == null)
			throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url ("
					+ url.toString() + ") use keys([protocol])");
		org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader
				.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
		return extension.export(arg0);
	}
 
	public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1)
			throws org.apache.dubbo.rpc.RpcException {
		if (arg1 == null)
			throw new IllegalArgumentException("url == null");
		org.apache.dubbo.common.URL url = arg1;
		
		// 根据URL的协议类型来指定拓展点,默认是dubbo
		String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
		if (extName == null)
			throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url ("
					+ url.toString() + ") use keys([protocol])");
		org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader
				.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
		return extension.refer(arg0, arg1);
	}
}

所以Dubbo源码中,可以根据URL的协议类型来指定拓展点!这在源码阅读分析中很重要。

标签:Dubbo,Protocol,dubbo,url,SPI,rpc,源码,apache,org
来源: https://blog.csdn.net/lisheng5218/article/details/113972048

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有