3. Dubbo源码解析之服务引用过程
服务引用过程主要包括。。。。
3.1 Dubbo自定义xml解析器
服务暴露过程中已经讲过,此处略过。
3.2 ReferenceBean 装配与调用
完成了对xml标签的解析后,Spring会通过registerBeanPostProcessors(beanFactory)
对 ReferenceBean 进行初始化,与 ServiceBean 在finishBeanFactoryInitialization(beanFactory);
步骤中初始化不同,具体原因是:ReferenceBean 实现了 FactoryBean 接口,因此 ReferenceBean 是一个 FactoryBean,需要用bean的引用去初始化,即getObject()
。看下具体调用过程:
AbstractApplicationContext#registerBeanPostProcessors
|- AbstractBeanFactory#getBean
|- AbstractAutowireCapableBeanFactory#createBean
|- AbstractAutowireCapableBeanFactory#doCreateBean
|- AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod
|- ConstructorResolver#createArgumentArray
|- ConstructorResolver#resolveAutowiredArgument
|- DefaultListableBeanFactory#resolveDependency
|- DefaultListableBeanFactory#doResolveDependency
|- DefaultListableBeanFactory#findAutowireCandidates
|- 下面接着。。。
BeanFactoryUtils#beanNamesForTypeIncludingAncestors
|- AbstractBeanFactory#getTypeForFactoryBean
|- AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck
|- AbstractAutowireCapableBeanFactory#createBeanInstance
|- AbstractAutowireCapableBeanFactory#instantiateBean
|-SimpleInstantiationStrategy#instantiate
|- BeanUtils.instantiateClass(constructorToUse);
从调用过程中分析 ServiceBean 与 ReferenceBean 进入代码分支不同的地方,发现在 AbstractBeanFactory#getTypeForFactoryBean
调用步骤时不同,ServiceBean 不会执行到这步,原因是ServiceBean 不是FactoryBean,代码如下:
// Check bean class whether we're dealing with a FactoryBean.
if (FactoryBean.class.isAssignableFrom(beanType)) {
if (!BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
beanType = getTypeForFactoryBean(beanName, mbd);
if (beanType == null) {
return false;
}
}
}
上述步骤仅仅完成 ReferenceBean 的初始化,因为它是一个 FactoryBean,所以会调用 getObject 获取引用Bean创造的对象,看下getObject是什么时候调用的?
AbstractApplicationContext#finishBeanFactoryInitialization
|- AbstractBeanFactory#createBean
...
|- AbstractBeanFactory#doGetBean
|- AbstractBeanFactory#getObjectForBeanInstance
|- FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
|- factory.getObject()
FactoryBeanRegistrySupport 提供了一些FactoryBean的相关方法供BeanFactory内部使用。FactoryBean生产的单例在 FactoryBeanRegistrySupport 成员变量 private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
中,
题外话:FactoryBean和FactoryBean生成的Bean的辨析
FactoryBean | FactoryBean生成的Bean | |
---|---|---|
种类 | FactoryBean是一个普通Bean,它和普通的Bean总体上没有区别 | FactoryBean生成的Bean是一种特殊的Bean |
创建途径 | 通过CreateBean方法创建 | 通过FactoryBean的getObject方法 |
是否是单例 | 配置决定 | 由FactoryBean的isSingleton方法决定的 |
单例存放点 | DefaultSingletonBeanRegistry的SingletonObjects | FactoryBeanRegistrySupport的factoryBeanObjectCache |
创建方式 | 可以像普通Bean进行依赖注入 | 因为是通过getObject方法生成,无法直接注入依赖 |
获取方法 | 需要在BeanName前加 '&' | 直接用BeanName |
3.3 服务引用过程
服务引用过程就是执行 getObject()
过程,如果dubbo配置引用时,设置了初始化 init="true"
,则会在初始化时执行该方法。
<dubbo:reference init="true" id="demoFacade" interface="com.gmr.dubbo.provider.remote.facade.DemoFacade" version="1.0" group="${dubbo.consumer.group}"/>
if (shouldInit()) {
getObject();
}
服务引用分为两种引用方式,第一种是使用服务直连的方式引用服务,第二种方式是基于注册中心进行引用。服务直连的方式仅适合在调试或测试服务的场景下使用,不适合在线上环境使用。
直连方式引用服务配置:
<dubbo:reference init="true" id="demoFacade" interface="com.gmr.dubbo.provider.remote.facade.DemoFacade" version="1.0" group="${dubbo.consumer.group}" url="dubbo://localhost:20882" />
添加URL配置就行。
3.3.1 处理配置
public void checkAndUpdateSubConfigs() {
// 用于检测 provider、application 等核心配置类对象是否为空,
// 若为空,则尝试从其他配置类对象中获取相应的实例。
completeCompoundConfigs();
// 启动配置中心
startConfigCenter();
// 如果没有ConsumerConfig创建一个默认的
checkDefault();
// 刷新ReferenceConfig配置
this.refresh();
if (getGeneric() == null && getConsumer() != null) {
setGeneric(getConsumer().getGeneric());
}
if (ProtocolUtils.isGeneric(getGeneric())) {
interfaceClass = GenericService.class;
} else {
try {
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, methods);
}
resolveFile();
// 如果没有ApplicationConfig创建一个默认的
checkApplication();
// 检查MetadataReportConfig,没有创建一个默认的
checkMetadataReport();
}
private void init() {
...
//
checkStubAndLocal(interfaceClass);
checkMock(interfaceClass);
...
}
对配置检查逻辑简单总结如下:
- 对一些配置进行填充和检查,只支持覆盖config类中显式定义的属性,不支持覆盖存储在“parameters”中的自定义参数。
- 启动配置中心,从dubbo2.7开始支持了配置中心动态修改配置
- 判断consumer是不是 GenericService,即泛化引用
- 如果配置了stub=true,检测是否存在存根类,检查存根类构造函数是否有且只有一个接口类参数
- 检测消费端Mock类是否合法
private void init() {
// 非泛化服务
if (!isGeneric()) {
...
// 获取方法列表,添加到 map 中
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if (methods.length == 0) {
map.put("methods", Constants.ANY_VALUE);
} else {
map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
}
}
...
// MethodConfig 遍历,可以配置重试次数
if (CollectionUtils.isNotEmpty(methods)) {
attributes = new HashMap<String, Object>();
for (MethodConfig methodConfig : methods) {
...
// 设置事件通知配置,比如 onreturn,onthrow,oninvoke等
attributes.put(methodConfig.getName(),
convertMethodConfig2AyncInfo(methodConfig));
}
}
// 创建代理类
ref = createProxy(map);
// 创建服务key
String serviceKey = URL.buildKey(interfaceName, group, version);
...
}
在服务引用初始化时,还进行了接口方法重试次数配置,事件通知配置等。
3.3.2 引用服务
createProxy
创建代理类,实现的主要功能:判断是本地引用还是远程引用,判断是直连引用还是注册中心引用,获取Invoker(多个时 Cluster 合并处理),创建代理类。
private T createProxy(Map<String, String> map) {
// 本地引用
if (shouldJvmRefer(map)) {
...
}
// 远程引用
else {
// 直连引用,调试用
if (url != null && url.length() > 0) {
...
}
// 注册中心引用
else {
checkRegistry();
// 加载注册中心URL
List<URL> us = loadRegistries(false);
...
}
// 单个注册中心或者单个服务直连
if (urls.size() == 1) {
// 构建invoker (RegistryProtocol)
invoker = refprotocol.refer(interfaceClass, urls.get(0));
}
// 多个注册中心或者多个服务直连,或者两者混合
else {
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
// 获取所有的Invoker
for (URL url : urls) {
invokers.add(refprotocol.refer(interfaceClass, url));
...
}
if (registryURL != null) {
...
// 合并invoker,创建 StaticDirecory 服务字典
invoker = cluster.join(new StaticDirectory(u, invokers));
} else {
invoker = cluster.join(new StaticDirectory(invokers));
}
}
}
// 可用性检查
// 元数据注册
// 生成代理类
return (T) proxyFactory.getProxy(invoker);
}
3.3.2.1 创建Invoker
Invoker是Dubbo的核心模型,代表一个可执行体,在服务提供方,用于调用服务提供类,在消费方,Invoker用于远程调用。invoker = refprotocol.refer(interfaceClass, urls.get(0));
创建invoker,动态代理产生的代码逻辑如下:
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
...
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;
String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
...
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);
}
}
此处,ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName)
会获取协议,具体调用过程是QosProtocolWrapper.refer()
-> ProtocolListenerWrapper.refer()
-> ProtocolFilterWrapper.refer()
-> RegisryProtocol.refer()
,具体调用逻辑是:
private T createExtension(String name) {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// registryProtocol 注入过程
injectExtension(instance);
// wrapper 注入过程
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T)
wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
}
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// protocol: registry -> zookeeper
url = URLBuilder.from(url)
.setProtocol(url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY))
.removeParameter(REGISTRY_KEY)
.build();
...
// group="a,b" or group="*"
Map<String, String> qs =
StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
String group = qs.get(Constants.GROUP_KEY);
if (group != null && group.length() > 0) {
if ((COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) {
return doRefer(getMergeableCluster(), registry, type, url);
}
}
return doRefer(cluster, registry, type, url);
}
若配置的group形式是 group=“a,b” or group="*",则调用getMergeableCluster方法,即MergeableCluster实例,否则(即只配置了一个group)会生成Cluster的Adaptive字节码。
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//${RegistryDirectory 创建与赋值}
//${subscribeUrl 创建}
// 注册服务引用
registry.register(directory.getRegisteredConsumerUrl());
// 建立路由链, 赋值到 RegistryDirectory 中
directory.buildRouterChain(subscribeUrl);
// 订阅(创建或共享消费者客户端,创建dubboInvoker)
directory.subscribe(
subscribeUrl.addParameter(CATEGORY_KEY,
PROVIDERS_CATEGORY + "," +
CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));
// 创建invoker
Invoker invoker = cluster.join(directory);
// 向本地注册表,注册消费者
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker;
}
-
注册服务引用
registry获取的是zookeeper协议,因此用的是 ZookeeperRegistry,父类是FailbackRegistry
FailbackRegistry#register |- ZookeeperRegistry#doRegister |- zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
将consumer的URL注册到zk,具体内容如下:
consumer://10.216.128.81/com.gmr.dubbo.provider.remote.facade.DemoFacade?application=dubbo-demo-consumer&category=consumers&check=false&default.check=false&default.cluster=failfast&default.group=test&default.lazy=false&default.reference.filter=-monitor&default.sticky=false&default.timeout=10000&default.version=1.0&dubbo=2.0.2&environment=test&group=test&init=true&interface=com.gmr.dubbo.provider.remote.facade.DemoFacade&lazy=false&logger=slf4j&methods=sayHello&organization=decision&owner=hzguomeiran&pid=23624&release=2.7.1&revision=1.0.20190524.local-SNAPSHOT&side=consumer&sticky=false×tamp=1561118213732&version=1.0
-
建立路由链
订阅url,如下:
consumer://10.216.128.81/com.gmr.dubbo.provider.remote.facade.DemoFacade?application=dubbo-demo-consumer&default.check=false&default.cluster=failfast&default.group=test&default.lazy=false&default.reference.filter=-monitor&default.sticky=false&default.timeout=10000&default.version=1.0&dubbo=2.0.2&environment=test&group=test&init=true&interface=com.gmr.dubbo.provider.remote.facade.DemoFacade&lazy=false&logger=slf4j&methods=sayHello&organization=decision&owner=hzguomeiran&pid=23624&release=2.7.1&revision=1.0.20190524.local-SNAPSHOT&side=consumer&sticky=false×tamp=1561118213732&version=1.0
private RouterChain(URL url) { List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class) .getActivateExtension(url, (String[]) null); List<Router> routers = extensionFactories.stream() .map(factory -> factory.getRouter(url)) .collect(Collectors.toList()); initWithRouters(routers); }
创建了路由链如下:
-
订阅,创建或共享消费者客户端
与注册consumer一样,用的是ZookeeperRegistry,代码如下:
protected void doSubscribe(final URL url, final NotifyListener listener) { //如果provider的service的接口配置的是“*” if (Constants.ANY_VALUE.equals(url.getServiceInterface())) { //获取服务分组根路径 String root = toRootPath(); //获取服务的NotifyListener ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url); if (listeners == null) { //如果没有则创建一个 zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); listeners = zkListeners.get(url); } ChildListener zkListener = listeners.get(listener); //如果没有子监听器则创建一个 if (zkListener == null) { listeners.putIfAbsent(listener, new ChildListener() { public void childChanged(String parentPath, List<String> currentChilds) { for (String child : currentChilds) { child = URL.decode(child); if (! anyServices.contains(child)) { anyServices.add(child); subscribe(url.setPath(child) .addParameters(Constants.INTERFACE_KEY, child, Constants.CHECK_KEY, String.valueOf(false)), listener); } } } }); zkListener = listeners.get(listener); } //向服务器订阅服务,注册中心会调用NotifyListener的notify函数返回服务列表 zkClient.create(root, false); //获取服务地址列表 List<String> services = zkClient.addChildListener(root, zkListener); if (services != null && services.size() > 0) { //如果存在服务 for (String service : services) { service = URL.decode(service); anyServices.add(service); //如果serviceInterface是“*”则从分组根路径遍历service并订阅所有服务 subscribe(url.setPath(service) .addParameters(Constants.INTERFACE_KEY, service, Constants.CHECK_KEY, String.valueOf(false)), listener); } } } else { //如果serviceInterface不是“*” // 则创建Zookeeper客户端索取服务列表,并通知(notify)消费者(consumer)这些服务可以用了 List<URL> urls = new ArrayList<URL>(); //获取类似于http://xxx.xxx.xxx.xxx/context/com.service.xxxService/consumer的地址 for (String path : toCategoriesPath(url)) { //获取例如com.service.xxxService对应的NotifyListener map ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url); if (listeners == null) { zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); listeners = zkListeners.get(url); } //获取ChildListener ChildListener zkListener = listeners.get(listener); if (zkListener == null) { listeners.putIfAbsent(listener, new ChildListener() { public void childChanged(String parentPath, List<String> currentChilds) { ZookeeperRegistry.this.notify(url,listener, toUrlsWithEmpty(url, parentPath, currentChilds)); } }); zkListener = listeners.get(listener); } //创建Zookeeper客户端 zkClient.create(path, false); List<String> children = zkClient.addChildListener(path, zkListener); if (children != null) { urls.addAll(toUrlsWithEmpty(url, path, children)); } } //提醒消费者 notify(url, listener, urls); } }
其实做了两件事,一个是创建ChildListener监听器,ZK注册监听器,当发生变化时,消费者可以监听到,监听到后也是通知消费者,另一个通知消费者,服务可以用了,最终调用的时服务字典(RegistryDirectory)的notify方法:
public synchronized void notify(List<URL> urls) { Map<String, List<URL>> categoryUrls = urls.stream() .filter(Objects::nonNull) .filter(this::isValidCategory) .filter(this::isNotCompatibleFor26x) .collect(Collectors.groupingBy(url -> { if (UrlUtils.isConfigurator(url)) { return CONFIGURATORS_CATEGORY; } else if (UrlUtils.isRoute(url)) { return ROUTERS_CATEGORY; } else if (UrlUtils.isProvider(url)) { return PROVIDERS_CATEGORY; } return ""; })); // configurator 路径 List<URL> configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList()); this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators); // routers 路径 List<URL> routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList()); toRouters(routerURLs).ifPresent(this::addRouters); // providers 路径 List<URL> providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList()); // 只刷新providers refreshOverrideAndInvoker(providerURLs); }
refreshOverrideAndInvoker -> refreshInvoker -> toInvokers -> invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), // dubbo 协议 url, providerUrl); -> dubboProtocol.refer
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException { optimizeSerialization(url); // create rpc invoker. DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers); invokers.add(invoker); return invoker; }
DubboProtocol 的 refer方法创建了 DubboInvoker,其中调用了
getClients(url)
方法,创建了消费者客户端。Dubbo是怎么解决粘包和半包的,用的是自定义的协议
DubboCodec
方式:bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { int heartbeatInterval = UrlUtils.getHeartbeat(getUrl()); NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this); ch.pipeline() .addLast("decoder", adapter.getDecoder()) .addLast("encoder", adapter.getEncoder()) .addLast("client-idle-handler", new IdleStateHandler(heartbeatInterval, 0, 0, MILLISECONDS)) .addLast("handler", nettyClientHandler); } });
将创建好的DubboInvoker 放到 RegistryDirectory 的 newUrlInvokerMap 成员变量中,
private volatile Map<String, Invoker<T>> urlInvokerMap;
注意:创建Netty客户端时,会根据提供者的IP和端口不同,会创建多个netty客户端,不同的接口可以共享一个netty客户端。
此外,在
refreshOverrideAndInvoker
方法中,还会设置RouterChain 的Invokers,在服务调用,路由时会用到,如果设置了多个组,还会合并invoker。routerChain.setInvokers(newInvokers); this.invokers = multiGroup ? toMergeInvokerList(newInvokers) : newInvokers; this.urlInvokerMap = newUrlInvokerMap;
-
集群获取invoker
public class Cluster$Adpative implements Cluster { public Invoker join(Directory arg0) throws Directory { ... URL url = arg0.getUrl(); String extName = url.getParameter("cluster", "failover"); Cluster extension = ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(extName); return extension.join(arg0); } }
这里只是对获取一个封装了 RegistryDirectory 的集群策略的invoker,比如 FailfastClusterInvoker
public class FailfastCluster implements Cluster { public final static String NAME = "failfast"; @Override public <T> Invoker<T> join(Directory<T> directory) throws RpcException { return new FailfastClusterInvoker<T>(directory); } }
最终创建的是MockClusterInvoker,如下图:
-
注册消费者
public static void registerConsumer(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) { ConsumerInvokerWrapper wrapperInvoker = new ConsumerInvokerWrapper(invoker, registryUrl, consumerUrl, registryDirectory); String serviceUniqueName = consumerUrl.getServiceKey(); Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName); if (invokers == null) { consumerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ConsumerInvokerWrapper>()); invokers = consumerInvokers.get(serviceUniqueName); } invokers.add(wrapperInvoker); }
创建 ConsumerInvokerWrapper,将消费者注册到本地缓存中。
public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<>();
3.3.2.2 创建代理
通过 proxyFactory.getProxy(invoker);
为服务接口创建代理类,最终会调用 JavassistProxyFactory
的 getProxy 方法:
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces)
.newInstance(new InvokerInvocationHandler(invoker));
}
创建 InvokerInvocationHandler,实现自JDK 的 InvocationHandler接口,拦截接口类的调用。
最终会调用proxy类的getProxy静态方法,利用 ClassGenerator 进行代理类创建
public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
// ${遍历接口列表,校验接口,拼接接口全限定名}
...
synchronized (cache) {
do {
// ${从缓存中获取 Reference<Proxy> 实例}
// 并发控制,保证只有一个线程可以进行后续操作
if (value == PendingGenerationMarker) {
try {
cache.wait();
} catch (InterruptedException e) {
}
}
} while (true);
}
ClassGenerator ccp = null, ccm = null;
try {
// 创建 ClassGenerator 对象
ccp = ClassGenerator.newInstance(cl);
// ${装配 ccp}
// 生成接口代理类
Class<?> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
ccm = ClassGenerator.newInstance(cl);
// // 生成 Proxy 实现类
Class<?> pc = ccm.toClass();
// 通过反射创建 Proxy 实例
proxy = (Proxy) pc.newInstance();
} catch (RuntimeException e) {
...
} finally {
...
synchronized (cache) {
if (proxy == null) {
cache.remove(key);
} else {
// 写缓存
cache.put(key, new WeakReference<Proxy>(proxy));
}
// 唤醒其他等待线程
cache.notifyAll();
}
}
return proxy;
}
ccp 用于为服务接口生成代理类,比如我们有一个 DemoService 接口,这个接口代理类就是由 ccp 生成的。ccm 则是用于为 org.apache.dubbo.common.bytecode.Proxy 抽象类生成子类,主要是实现 Proxy 类的抽象方法。下面以 org.apache.dubbo.demo.DemoService 这个接口为例,来看一下该接口代理类代码大致是怎样的(忽略 EchoService 接口)。
package org.apache.dubbo.common.bytecode;
public class proxy0 implements org.apache.dubbo.demo.DemoService {
public static java.lang.reflect.Method[] methods;
private java.lang.reflect.InvocationHandler handler;
public proxy0() {
}
public proxy0(java.lang.reflect.InvocationHandler arg0) {
handler = $1;
}
public java.lang.String sayHello(java.lang.String arg0) {
Object[] args = new Object[1];
args[0] = ($w) $1;
Object ret = handler.invoke(this, methods[0], args);
return (java.lang.String) ret;
}
}
发现消费者调用时,其实用的是 InvokerInvocationHandler 进行处理的。
<dubbo:reference init="true" id="demoFacade" interface="com.gmr.dubbo.provider.remote.facade.DemoFacade" version="1.0" group="${dubbo.consumer.group}"/>
其实就是 ReferenceBean 的接口代理引用 ref
/**
* The interface proxy reference
*/
private transient volatile T ref;