五Dubbo服务引用源码分析--2创建远程调用的代理-2.5开启consumer端NettyClient
五Dubbo服务引用源码分析--2创建远程调用的代理-2.5开启consumer端NettyClient
/**…………NettyClient--开启consumer端………… */
此时url=dubbo://192.168.0.100:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demotest-consumer&bean.name=com.alibaba.dubbo.demo.DemoService&check=false&codec=dubbo&dubbo=2.0.2&generic=false&heartbeat=60000&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=75508&qos.enable=false®ister.ip=192.168.0.100&remote.timestamp=1672381137107&side=consumer×tamp=1672387055607
public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
//NC1 wrapChannelHandler(url, handler)-构建handler链
//NC2 super(url,handler)
super(url, wrapChannelHandler(url, handler));
}
//NC1 wrapChannelHandler(url, handler)-构建handler链
同provider端
AbstractClient
protected static ChannelHandler wrapChannelHandler(URL url, ChannelHandler handler) {
url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
url = url.addParameterIfAbsent(Constants.THREADPOOL_KEY, Constants.DEFAULT_CLIENT_THREADPOOL);
return ChannelHandlers.wrap(handler, url);
}
ChannelHandlers
public static ChannelHandler wrap(ChannelHandler handler, URL url) {
return ChannelHandlers.getInstance().wrapInternal(handler, url);
}
执行后的handler为:
由内到外的ChanelHandler处理链:
DubboProtocol.ExchangeHandlerAdapter
HeaderExchangeHandler主要还是管理连接等。
DecodeHandler主要是对请求进行解码。
AllChannelHandler是主要负责线程管理。
HeartbeatHandler主要负责心跳检测。
MultiMessageHandler主要负责将Dubbo内部定义的多条消息的聚合消息进行拆分处理。
NettyHandler
构造的channelhandler链,同provider端相同。
//NC2 super(url,handler)
public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
super(url, handler);
send_reconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, false);
shutdown_timeout = url.getParameter(Constants.SHUTDOWN_TIMEOUT_KEY, Constants.DEFAULT_SHUTDOWN_TIMEOUT);
// The default reconnection interval is 2s, 1800 means warning interval is 1 hour.
reconnect_warning_period = url.getParameter("reconnect.waring.period", 1800);
try {
//NC2.1 doOpen consumer端打开端口
doOpen();
} catch (Throwable t) {
close();
throw new RemotingException(url.toInetSocketAddress(), null,
"Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()
+ " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);
}
try {
//NC2.2 connect 连接
connect();
//NC2.1 doOpen consumer端pipeline、channelHandler配置
NettyClient
protected void doOpen() throws Throwable {
NettyHelper.setNettyLoggerFactory();
bootstrap = new ClientBootstrap(channelFactory); //创建bootstrap启动类
// config
// @see org.jboss.netty.channel.socket.SocketChannelConfig
bootstrap.setOption("keepAlive", true);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("connectTimeoutMillis", getConnectTimeout());
//以nettyclient中的handler,创建NettyHandler
final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", adapter.getDecoder());
pipeline.addLast("encoder", adapter.getEncoder());
pipeline.addLast("handler", nettyHandler);
return pipeline;
}
});
}
doOpen创建netty的启动配置类,然后设置pipeline、添加channelHandler处理器。
/** …………………消费端connect请求…………………*/
//NC2.2 AbstractClient.connect-->NettyClient.doConnect 连接
AbstractClient
protected void connect() throws RemotingException {
connectLock.lock();
try {
if (isConnected()) {
return;
}
initConnectStatusCheckCommand();
//连接provider端
doConnect();
if (!isConnected()) {
throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
+ NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
+ ", cause: Connect wait timeout: " + getConnectTimeout() + "ms.");
} else {
if (logger.isInfoEnabled()) {
logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
+ NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
+ ", channel is " + this.getChannel());
}
}
reconnect_count.set(0);
reconnect_error_log_flag.set(false);
} catch (RemotingException e) {
throw e;
} catch (Throwable e) {
throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
+ NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
+ ", cause: " + e.getMessage(), e);
} finally {
connectLock.unlock();
}
}
NettyClient
@Override
protected void doConnect() throws Throwable {
long start = System.currentTimeMillis();
//bootstrap辅助类连接
//getConnectAddress()返回InetSocketAddress,其中addr:port为192.168.0.100:20880
ChannelFuture future = bootstrap.connect(getConnectAddress()); //异步connect连接
try {
boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
//连接成功后,设置channel关注事件为read、write
if (ret && future.isSuccess()) {
Channel newChannel = future.getChannel();
newChannel.setInterestOps(Channel.OP_READ_WRITE);
try {
// Close old channel
Channel oldChannel = NettyClient.this.channel; // copy reference
if (oldChannel != null) {
try {
if (logger.isInfoEnabled()) {
logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel);
}
oldChannel.close();
} finally {
NettyChannel.removeChannelIfDisconnected(oldChannel);
}
}
} finally {
if (NettyClient.this.isClosed()) {
try {
if (logger.isInfoEnabled()) {
logger.info("Close new netty channel " + newChannel + ", because the client closed.");
}
newChannel.close();
} finally {
NettyClient.this.channel = null;
NettyChannel.removeChannelIfDisconnected(newChannel);
}
} else {
NettyClient.this.channel = newChannel;
}
}
} else if (future.getCause() != null) {
throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
+ getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause());
} else {
throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
+ getRemoteAddress() + " client-side timeout "
+ getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client "
+ NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
}
} finally {
if (!isConnected()) {
future.cancel();
}
}
}
连接操作中, 使用netty的辅助类bootstrap异步连接;然后根据future判断连接是否成功。连接成功后,将channel关注事件设置为read、write。
//INV2.2 DubboInvoker
然后返回INV2 DubboProtocol.refer
DubboProtocol.refer
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// 创建RPC功能的invoker
//INV2.1 getClients(url)
//INV2.2 DubboInvoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);//invokers为null
//将创建好的invoker加入集合
invokers.add(invoker);
return invoker;
}
此时,创建DubboInvoker,其内的客户端参数如下:
public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) {
super(serviceType, url, new String[]{Constants.INTERFACE_KEY, Constants.GROUP_KEY, Constants.TOKEN_KEY, Constants.TIMEOUT_KEY});
this.clients = clients;
// get version.
this.version = url.getParameter(Constants.VERSION_KEY, "0.0.0");
this.invokers = invokers;
}
//INV1.1 buildInvokerChain--同provider端
然后执行到ProtocolFilterWrapper.refer处,对invoker构造拦截器链。这里过程和provider端相同
ProtocolFilterWrapper
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
invoker创建拦截器链后的链式结构,如上:
ConsumerContextFilter->FutureFilter->MonitorFilter->DubboInvoker。
//SUB2.2.2.1.1 toInvokers(invokerUrls)--构造RegistryDirectory$InvokerDelegate
这里,将buildInvokerChain(protocol.refer(type, url)构造的invoker拦截器链,传入serviceType=demoService,providerURL等,构造成InvokerDelegate.
//SUB2.2.2.1.2 toMethodInvokers(newUrlInvokerMap)-略
然后返回//SUB2.2.2.1 refreshInvoker(invokerUrls)。toMethodInvokers方法,是构建method和invoker的对应关系,存入map中
private void refreshInvoker(List<URL> invokerUrls) {
//SUB2.2.2.1.1 toInvokers(invokerUrls)
Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls);// Translate url list to Invoker map
//SUB2.2.2.1.2 toMethodInvokers(newUrlInvokerMap)
Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // Change method
newUrlInvokerMap是转换成的新的key:invoker的map存储
返回的newMethodInvokerMap,是分析新创建的invoker的map,将其解析为method:invoker对应的map关系存储。代码执行过程略,看其执行结果:
REFER2.2.4 cluster$Adaptive.join(directory)
然后,返回REFER2.2 doRefer
RegistryProtocol
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//REFER2.2.1 RegistryDirectory
RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
directory.setRegistry(registry);//zookeeperRegistry
directory.setProtocol(protocol);//Protocol$Adaptive
// REFER_KEY的全部属性
Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
//构造consumerURL(订阅注册中心的url)--协议头为consumer,路径名称为demoService,参数对为refer服务的参数
//consumer://192.168.0.101/com.alibaba.dubbo.demo.DemoService?application=demotest-consumer&dubbo=2.0.2&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=57858&qos.enable=false&side=consumer×tamp=1672287700727
URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
&& url.getParameter(Constants.REGISTER_KEY, true)) {
//REFER2.2.2 zookeeperRegistry.register
registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
Constants.CHECK_KEY, String.valueOf(false)));
}
//REFER2.2.3 registryDirectory.subscribe
directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
Constants.PROVIDERS_CATEGORY
+ "," + Constants.CONFIGURATORS_CATEGORY
+ "," + Constants.ROUTERS_CATEGORY));
//REFER2.2.4 cluster$Adaptive.join(directory)
Invoker invoker = cluster.join(directory);
//REFER2.2.5 ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory)
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker;
}
然后,Cluster
将 Directory
中的多个 Invoker
伪装成一个 Invoker
,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。
此时,初始化并完成subscribe订阅后,刷新过invokers后的RegistryDierctory对象及属性如下:
public class Cluster$Adaptive implements com.alibaba.dubbo.rpc.cluster.Cluster {
public com.alibaba.dubbo.rpc.Invoker join(com.alibaba.dubbo.rpc.cluster.Directory arg0) throws com.alibaba.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
//zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=demotest-consumer&bean.name=com.alibaba.dubbo.demo.DemoService&check=false&dubbo=2.0.2&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=14888&qos.enable=false®ister.ip=192.168.0.101&remote.timestamp=1672381137107&side=consumer×tamp=1672478114604
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("cluster", "failover");//默认失败重试集群failoverCluster
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url(" + url.toString() + ") use keys([cluster])");
com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class).getExtension(extName);
//TAG1.3.1 MockClusterWrapper/FailoverCluster.join
return extension.join(arg0);
}
可知返回的cluster集群,是一个wrapper机制包裹上MockClusterWrapper的类。
REFER2.2.4.1 MockClusterWrapper.join--创建MockClusterInvoker
-
Cluster是一个通用代理类,会根据URL中的cluster参数值定位到实际的Cluster实现类也就是FailoverCluster。这里用到了@SPI注解,也就是需要ExtensionLoader扩展点加载机制,而该机制在实例化对象时,会在实例化后自动套上Wapper;
-
但是是集群模式所以需要Dubbo中另外一个核心机制——Mock。Mock可以在测试中模拟服务调用的各种异常情况,还可以实现服务降级。在MockerClusterInvoker中,Dubbo先检查URL中是否存在mock参数。(这个参数可以通过服务治理后台Consumer端的屏蔽和容错进行设置或者直接动态设置mock参数值)如果存在force开头,这不发起远程调用直接执行降级逻辑。如果存在fail开头,则在远程调用异常时才会执行降级逻辑;
-
可以说注册中心为集群模式时,Invoker就会外面多包裹一层mock逻辑。是通过Wapper机制实现的。最终可以在调用或者重试时,每次都通过Dubbo内部的负载均衡机制选出多个Invoker中的一个进行调用。
public class MockClusterWrapper implements Cluster {
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return new MockClusterInvoker<T>(directory,
//TAG1.3.1.1 FailoverCluster.join
this.cluster.join(directory));
}
此处,创建MockClusterInvoker对象,该对象内部存储cluster.join(directory)创建的invoker(这个对象是cluster集群对象对directory中的多个invoker对象,包裹了failover逻辑后伪装成一个invoker,其内包含容错逻辑,在调用失败后,选择下一个invoker)。
public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
this.directory = directory;
this.invoker = invoker;
}
/**……………………………………………………………………………………invoker.invoke调用逻辑……………………………………………………………………………………………………………… */
@Override
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
/**………………………………………………………………方法参数中不包含force/fail,正常调用…………………………………………………… */
if (value.length() == 0 || value.equalsIgnoreCase("false")) {
//转发给内部的invoker类,调用
result = this.invoker.invoke(invocation);
}
/**………………………………………………………………方法参数中包含force--不调用,直接服务降级…………………………………………………… */
else if (value.startsWith("force")) {
if (logger.isWarnEnabled()) {
logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
}
//force:direct mock
result = doMockInvoke(invocation, null);
}
/**………………………………………………………………方法参数中包含fail--调用失败,服务降级处理…………………………………………………… */
else {
//fail-mock
try {
result = this.invoker.invoke(invocation);
} catch (RpcException e) {
if (e.isBiz()) {
throw e;
} else {
if (logger.isWarnEnabled()) {
logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
}
result = doMockInvoke(invocation, e);
}
}
}
return result;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Result doMockInvoke(Invocation invocation, RpcException e) {
Result result = null;
Invoker<T> minvoker;
List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
if (mockInvokers == null || mockInvokers.isEmpty()) {
minvoker = (Invoker<T>) new MockInvoker(directory.getUrl());
} else {
minvoker = mockInvokers.get(0);
}
try {
result = minvoker.invoke(invocation);
} catch (RpcException me) {
if (me.isBiz()) {
result = new RpcResult(me.getCause());
} else {
throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
}
} catch (Throwable me) {
throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
}
return result;
}
//REFER2.2.4.2 FailoverCluster.join--创建FailoverClusterInvoker
public class FailoverCluster implements Cluster {
public final static String NAME = "failover";
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
//创建包含失败重试逻辑的invoker
return new FailoverClusterInvoker<T>(directory);
}
REFER2.2.5 ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory)
然后,将consumer和provider注册存入ProviderConsumerRegTable,方法参数此时如下:
public static void registerConsumer(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
ConsumerInvokerWrapper wrapperInvoker = new ConsumerInvokerWrapper(invoker, registryUrl, consumerUrl, registryDirectory);
//com.alibaba.dubbo.demo.DemoService
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);
}
TAG1.3 proxyFactory.getProxy(invoker)
public class ProxyFactory$Adaptive implements com.alibaba.dubbo.rpc.ProxyFactory {
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");//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);
//TAG1.3.1 StubProxyFactoryWrapper.getProxy
return extension.getProxy(arg0);
}
获取stub包裹的ProxyFactory。
TAG1.3.1 StubProxyFactoryWrapper.getProxy
StubProxyFactoryWrapper
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
//TAG1.3.1.1 JavassistProxyFactory.getProxy 创建代理对象
T proxy = proxyFactory.getProxy(invoker);
if (GenericService.class != invoker.getInterface()) {
String stub = invoker.getUrl().getParameter(Constants.STUB_KEY, invoker.getUrl().getParameter(Constants.LOCAL_KEY));
/**………………………………………………………………………………………………………………处理stub………………………………………………………………………………………………………… */
if (ConfigUtils.isNotEmpty(stub)) {
Class<?> serviceType = invoker.getInterface();
if (ConfigUtils.isDefault(stub)) {
if (invoker.getUrl().hasParameter(Constants.STUB_KEY)) {
stub = serviceType.getName() + "Stub";
} else {
stub = serviceType.getName() + "Local";
}
}
try {
Class<?> stubClass = ReflectUtils.forName(stub);
if (!serviceType.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + serviceType.getName());
}
try {
Constructor<?> constructor = ReflectUtils.findConstructor(stubClass, serviceType);
proxy = (T) constructor.newInstance(new Object[]{proxy});
//export stub service
URL url = invoker.getUrl();
if (url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT)) {
url = url.addParameter(Constants.STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
url = url.addParameter(Constants.IS_SERVER_KEY, Boolean.FALSE.toString());
try {
export(proxy, (Class) invoker.getInterface(), url);
} catch (Exception e) {
LOGGER.error("export a stub service error.", e);
}
}
} catch (NoSuchMethodException e) {
throw new IllegalStateException("No such constructor \"public " + stubClass.getSimpleName() + "(" + serviceType.getName() + ")\" in stub implementation class " + stubClass.getName(), e);
}
} catch (Throwable t) {
LOGGER.error("Failed to create stub implementation class " + stub + " in consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", cause: " + t.getMessage(), t);
// ignore
}
}
}
return proxy;
}
TAG1.3.1.1 JavassistProxyFactory.getProxy
public abstract class AbstractProxyFactory implements ProxyFactory {
@Override
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
return getProxy(invoker, false);
}
public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
Class<?>[] interfaces = null;
//invoker.getUrl()获取url为zookeeper://127.0.0.1:2181,即注册中心url
//这里获取"interfaces"参数,是获取多个接口
String config = invoker.getUrl().getParameter("interfaces"); //null
/**……………………………………………………处理多个interfaces情况………………………………………………………………………… */
if (config != null && config.length() > 0) {
String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null && types.length > 0) {
//将invoker.getInterface、EchoService加入interfaces集合中
interfaces = new Class<?>[types.length + 2];
interfaces[0] = invoker.getInterface();
interfaces[1] = EchoService.class;
for (int i = 0; i < types.length; i++) {
interfaces[i + 1] = ReflectUtils.forName(types[i]);
}
}
}
if (interfaces == null) {
//创建两个Class对象--DemoService、
interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
}
//generic=false
if (!invoker.getInterface().equals(GenericService.class) && generic) {
int len = interfaces.length;
Class<?>[] temp = interfaces;
interfaces = new Class<?>[len + 1];
System.arraycopy(temp, 0, interfaces, 0, len);
interfaces[len] = GenericService.class;
}
//交给子类实现
return getProxy(invoker, interfaces);
}
public class JavassistProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
//调用javassist框架,创建代理方式创建代理对象
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
使用javassist的动态代理,创建实例对象。传入调用处理器,所有的方法调用,会交给此调用方法调用管理器,拦截执行
package com.alibaba.dubbo.rpc.proxy;
//dubbo实现的InvocationHandler
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler) {
this.invoker = handler;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();//方法名
Class<?>[] parameterTypes = method.getParameterTypes();//方法参数类型
//声明method的类是Object.class
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
//代理对象的方法调用,会转交给invoker.invoke执行
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}
最后,在referenceConfig中创建的ref代理对象如下:
DubboInvoker具有通信功能,其内部初始化并开启Netty服务的NettyClient