Dubbo源码 从API方式配置开始
/**
* 使用api的方式配置dubbo
* ApiProviderConfiguration
*/
public class ApiProviderConfiguration {
public static void main(String[] args) throws Exception {
// 服务实现
OrderService orderService = new OrderServiceImpl();
// 当前应用配置。 请学习ApplicationConfig的API
ApplicationConfig application = new ApplicationConfig();
application.setName("hello-world-app");
Map<String, String> appParameters = new HashMap<String, String>();
appParameters.put("qos.enable", "false");
application.setParameters(appParameters);
// 连接注册中心配置。 请学习RegistryConfig的API
RegistryConfig registry = new RegistryConfig("224.5.6.7:1234", "multicast");
//registry.setDynamic(true); // 动态注册,服务出现问题自动处理
// 服务提供者协议配置
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("dubbo");
protocol.setPort(12345);
protocol.setThreads(200);
// 注意:ServiceConfig为重对象,内部封装了与注册中心的连接,以及开启服务端口
// 服务提供者暴露服务配置。请学习ServiceConfig的API
// 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
ServiceConfig<OrderService> service = new ServiceConfig<OrderService>();
service.setApplication(application);
service.setRegistry(registry); // 多个注册中心可以用setRegistries()
service.setProtocol(protocol); // 多个协议可以用setProtocols()
service.setInterface(OrderService.class);
service.setRef(orderService);
service.setVersion("1.0.0");
// 暴露及注册服务
service.export(); //入口
System.in.read(); // 按任意键退出
}
}
复制代码
暴露服务,检查一些配置是不是为空
检查参数的protected synchronized void doExport() {
if (this.unexported) {
throw new IllegalStateException("Already unexported!");
} else if (!this.exported) {
this.exported = true;
if (this.interfaceName != null && this.interfaceName.length() != 0) {
this.checkDefault();
if (this.provider != null) {
if (this.application == null) {
this.application = this.provider.getApplication();
}
if (this.module == null) {
this.module = this.provider.getModule();
}
if (this.registries == null) {
this.registries = this.provider.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.provider.getMonitor();
}
if (this.protocols == null) {
this.protocols = this.provider.getProtocols();
}
}
if (this.module != null) {
if (this.registries == null) {
this.registries = this.module.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.module.getMonitor();
}
}
if (this.application != null) {
if (this.registries == null) {
this.registries = this.application.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.application.getMonitor();
}
}
if (this.ref instanceof GenericService) {
this.interfaceClass = GenericService.class;
if (StringUtils.isEmpty(this.generic)) {
this.generic = Boolean.TRUE.toString();
}
} else {
try {
this.interfaceClass = Class.forName(this.interfaceName, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException var5) {
throw new IllegalStateException(var5.getMessage(), var5);
}
this.checkInterfaceAndMethods(this.interfaceClass, this.methods);
this.checkRef();
this.generic = Boolean.FALSE.toString();
}
Class stubClass;
if (this.local != null) {
if ("true".equals(this.local)) {
this.local = this.interfaceName + "Local";
}
try {
stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.local);
} catch (ClassNotFoundException var4) {
throw new IllegalStateException(var4.getMessage(), var4);
}
if (!this.interfaceClass.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The local implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
}
}
if (this.stub != null) {
if ("true".equals(this.stub)) {
this.stub = this.interfaceName + "Stub";
}
try {
stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.stub);
} catch (ClassNotFoundException var3) {
throw new IllegalStateException(var3.getMessage(), var3);
}
if (!this.interfaceClass.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
}
}
this.checkApplication();
this.checkRegistry();
this.checkProtocol();
appendProperties(this);
this.checkStub(this.interfaceClass);
this.checkMock(this.interfaceClass);
if (this.path == null || this.path.length() == 0) {
this.path = this.interfaceName;
}
this.doExportUrls();//在到这里
ProviderModel providerModel = new ProviderModel(this.getUniqueServiceName(), this, this.ref);
ApplicationModel.initProviderModel(this.getUniqueServiceName(), providerModel);
} else {
throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
}
}
}
复制代码
在循环中,url协议头部改成registry,将注册中心作为参数放到后面。url就变成下面这样。
以上方法就是做了一个协议头的转换。因为Dubbo中URL是一个非常重要的契约,所有扩展点都要遵守。所有扩展点的参数都包含URL参数,URL作为上下文信息贯穿整个扩展点设计体系。URL采用标准格式:protocol://username:passward@host:port/path?key=value&key=value.
进入这个方法
往下看暴露服务的map信息
开始注册
代理工厂。关键地方,给了3个参数,ref(接口的具体实现),(Class)interfaceClass ,注册中心的urlInvoker<?> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, registryURL.addParameterAndEncoded("export", url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter =protocol.export(wrapperInvoker);
this.exporters.add(exporter);
复制代码
看下ProxyFactory的getExtensionLoader扩展加载器都私有化了。getAdaptiveExtension属于自适应扩展
private static final ProxyFactory proxyFactory = (ProxyFactory)ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
复制代码
SPI ExtensionLoader 扩展点加载器?做了什么?怎么做到自适应?
进到ProxyFactory接口中
配置信息Invoker和Exporter
Invoker是实体域,Dubbo的核心模型,其他模型都向它靠拢或转换成它,它代表一个可以执行体。可以将所有需要代理的方法,用Invoker进行抽象,转换。
API与SPI
Dubbo框架有两类用户,框架使用者和扩展开发者。为对两类用户进行隔离,使用者通过API,开发者使用SPI。使用者无需从编码层面知道扩展的类型,只需配置即可;扩展着也能很方便的扩展功能,不需要考虑适应不同的编码场景。Dubbo没有采用JDK的SPI,而是自己实现了一套。
进入ExtensionLoader类类似SpringIOC
通过class反射类来构造class对象实例,injectExtension方法通过setter注入扩展类中的依赖的其他扩展点。包装类Wrapper,封装了通用的逻辑,通过有无当前扩展参数构造函数来判断,并注入依赖扩展。
在crateExtension方法中的
Set<Class<?>> wrapperClasses = this.cachedWrapperClasses;
Class wrapperClass;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for(Iterator i$ = wrapperClasses.iterator(); i$.hasNext(); instance = this.injectExtension(wrapperClass.getConstructor(this.type).newInstance(instance))) {
wrapperClass = (Class)i$.next();
}
}
return instance;
复制代码
重要 动态生成代码(类)createAdaptiveExtensionClassCode 只会在方法上起作用 具体生成的类。扩展点的类必须有@SPI类注解和@Adaptive方法注解才会动态生成代码。
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adaptive implements com.alibaba.dubbo.rpc.ProxyFactory {
public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws com.alibaba.dubbo.rpc.RpcException {
if (arg2 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg2;
String extName = url.getParameter("proxy", "javassist");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
return extension.getInvoker(arg0, arg1, arg2);
}
public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0, boolean arg1) throws com.alibaba.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("proxy", "javassist");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
return extension.getProxy(arg0, arg1);
}
public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("proxy", "javassist");
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);
return extension.getProxy(arg0);
}
}
复制代码
生成类的class
再来看看扩展点的包装类