### 发布服务到本地
发布本地服务的代码在ServiceConfig.doExportUrlsFor1Protocol方法里
主要代码如下
// 通过动态代理工厂生成实现类调用器Invoker, Invoker相当于动态代理类
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
// 只是将代理和配置放到一起
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
// 发布服务到协议中,现在是InjvmProtocol
Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
默认用的动态代理工厂是JavassistProxyFactory
通过AbstractProxyInvoker类封装成Invoker
Wrapper是通过字节码技术给类增加了几个增强方法
想查看javassist生成的class源代码可以通过CtClass类的writeFile方法输出到本地文件,再反编译
// JavassistProxyFactory.java
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper类不能正确处理带$的类名
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf(‘$‘) < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
JdkProxyFactory则是直接用反射调用
// JdkProxyFactory.java
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
Method method = proxy.getClass().getMethod(methodName, parameterTypes);
return method.invoke(proxy, arguments);
}
};
}
接下来就是把invoker发布
用的协议是InjvmProtocol
injvm协议非常简单,不用监听端口什么的,直接返回InjvmExporter实例
到这里发布服务到本地已经完成了
// InjvmProtocol.java
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
}
// InjvmExporter.java
class InjvmExporter<T> extends AbstractExporter<T> {
private final String key;
private final Map<String, Exporter<?>> exporterMap;
InjvmExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {
super(invoker);
this.key = key;
this.exporterMap = exporterMap;
exporterMap.put(key, this);
}
public void unexport() {
super.unexport();
exporterMap.remove(key);
}
}
### 调用本地服务
服务引用在初始化时生成目标接口的代理实现
在ReferenceConfig.createProxy方法生成
// ReferenceConfig.java
if (isJvmRefer) {
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
// 通过服务协议获取服务调用器, refprotocol和发布时的protocol是同一实例
invoker = refprotocol.refer(interfaceClass, url);
if (logger.isInfoEnabled()) {
logger.info("Using injvm service " + interfaceClass.getName());
}
}
// InjvmProtocol.java
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
// exporterMap保存了已发布的服务,因为发布和引用都用的同一个protocol实例,所以exporterMap也是同一个。
return new InjvmInvoker<T>(serviceType, url, url.getServiceKey(), exporterMap);
}
创建动态代理返回
默认用的动态代理工厂是JavassistProxyFactory,用字节码技术生成目标接口的代理类
如果使用JdkProxyFactory,则没有字节码生成类的步骤,直接动态代理调用Invoker类的invoke方法
// ReferenceConfig.java
// 创建服务代理
return (T) proxyFactory.getProxy(invoker);
// JavassistProxyFactory.java
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
// JdkProxyFactory.java
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
}
// 重点**
// javassist生成的类继承自Proxy,并实现了目标接口,目标方法会被实现一次,handler是上面的InvokerInvocationHandler实例
// 以下是生成的方法
public String sayHello(String $1) {
Object[] args = new Object[1];
args[0] = ($w)$1;
Object ret = handler.invoke(this, methods[0], args);
return (java.lang.String)ret;
}
// InvokerInvocationHandler.java
// 该类实现了InvocationHandler,目的是支持jdk动态代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
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]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
最后在调用目标方法的时候,通过调用方invoker找到服务方invoker
// InjvmInvoker.java
// 此时在调用方invoker实例
public Result doInvoke(Invocation invocation) throws Throwable {
// 通过exporterMap找到服务方exporter
Exporter<?> exporter = InjvmProtocol.getExporter(exporterMap, getUrl());
if (exporter == null) {
throw new RpcException("Service [" + key + "] not found.");
}
RpcContext.getContext().setRemoteAddress(NetUtils.LOCALHOST, 0);
// 拿出服务方invoker并调用方法
return exporter.getInvoker().invoke(invocation);
}