ProxyFactory
//就是为了获取一个接口的代理类,例如获取一个远程接口的代理。
@SPI("javassist")
public interface ProxyFactory {
@Adaptive({"proxy"})
T getProxy(Invoker invoker) throws RpcException;
//针对client端,创建接口的代理对象,例如DemoService的接口。
@Adaptive({"proxy"})
T getProxy(Invoker invoker, boolean generic) throws RpcException;
//针对server端,将服务对象,如DemoServiceImpl包装成一个Invoker对象。
@Adaptive({"proxy"})
Invoker getInvoker(T proxy, Class type, URL url) throws RpcException;
}
复制代码
AbstractProxyFactory
/**
* 主要是实现了 #getProxy(invoker)
*/
public abstract class AbstractProxyFactory implements ProxyFactory {
@Override
public T getProxy(Invoker invoker) throws RpcException {
return getProxy(invoker, false);
}
@Override
public T getProxy(Invoker invoker, boolean generic) throws RpcException {
Class>[] interfaces = null;
String config = invoker.getUrl().getParameter("interfaces");
if (config != null && config.length() > 0) {
String[] types = Constants.COMMA_SPLIT_PATTERN.split(config);
if (types != null && types.length > 0) {
interfaces = new Class>[types.length + 2];
interfaces[0] = invoker.getInterface();
interfaces[1] = EchoService.class;
for (int i = 0; i < types.length; i++) {
interfaces[i + 2] = ReflectUtils.forName(types[i]);
}
}
}
if (interfaces == null) {
interfaces = new Class>[]{invoker.getInterface(), EchoService.class};
}
if (!GenericService.class.isAssignableFrom(invoker.getInterface()) && generic) {
int len = interfaces.length;
Class>[] temp = interfaces;
interfaces = new Class>[len + 1];
System.arraycopy(temp, 0, interfaces, 0, len);
interfaces[len] = com.alibaba.dubbo.rpc.service.GenericService.class;
}
return getProxy(invoker, interfaces);
}
//调用具体的实现
public abstract T getProxy(Invoker invoker, Class>[] types);
}
复制代码
JavassistProxyFactory
public class JavassistProxyFactory extends AbstractProxyFactory {
@Override
public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.getProxy(interfaces)//这里产生字节码
.newInstance(new InvokerInvocationHandler(invoker));
}
}
复制代码
Proxy
//该方法主要是利用javasist生成代理类
public static Proxy getProxy(ClassLoader cl, Class>... ics) {
//...
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ics.length; i++) {
String itf = ics[i].getName();//获取接口名
Class> tmp = null;
try {
tmp = Class.forName(itf, false, cl);
} catch (ClassNotFoundException e) {}
sb.append(itf).append(';');
}
// use interface class name list as key.
String key = sb.toString();
// get cache by class loader.
Map cache;
synchronized (ProxyCacheMap) {
cache = ProxyCacheMap.get(cl);
if (cache == null) {
cache = new HashMap();
ProxyCacheMap.put(cl, cache);
}
}
Proxy proxy = null;
synchronized (cache) {
do {
Object value = cache.get(key);
if (value instanceof Reference>) {
proxy = (Proxy) ((Reference>) value).get();
if (proxy != null)
return proxy;
}
if (value == PendingGenerationMarker) {
try {
cache.wait();
} catch (InterruptedException e) {
}
} else {
cache.put(key, PendingGenerationMarker);
break;
}
}
while (true);
}
long id = PROXY_CLASS_COUNTER.getAndIncrement();
String pkg = null;
ClassGenerator ccp = null, ccm = null;
try {
ccp = ClassGenerator.newInstance(cl);
Set worked = new HashSet();
List methods = new ArrayList();
for (int i = 0; i < ics.length; i++) {
if (!Modifier.isPublic(ics[i].getModifiers())) {
String npkg = ics[i].getPackage().getName();
if (pkg == null) {
pkg = npkg;
} else {
if (!pkg.equals(npkg))
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
ccp.addInterface(ics[i]);
for (Method method : ics[i].getMethods()) {
String desc = ReflectUtils.getDesc(method);
if (worked.contains(desc))
continue;
worked.add(desc);
int ix = methods.size();
Class> rt = method.getReturnType();
Class>[] pts = method.getParameterTypes();
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
for (int j = 0; j < pts.length; j++)
code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
if (!Void.TYPE.equals(rt))
code.append(" return ").append(asArgument(rt, "ret")).append(";");
methods.add(method);
ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
}
}
if (pkg == null)
pkg = PACKAGE_NAME;
// 接口的实现类
String pcn = pkg + ".proxy" + id;
ccp.setClassName(pcn);
ccp.addField("public static java.lang.reflect.Method[] methods;");
ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
ccp.addConstructor(Modifier.PUBLIC, new Class>[]{InvocationHandler.class}, new Class>[0], "handler=$1;");
ccp.addDefaultConstructor();
Class> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// 生成当前Proxy的子类,实现newInstance()方法
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
ccm.setClassName(fcn);
ccm.addDefaultConstructor();
ccm.setSuperClass(Proxy.class);
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
Class> pc = ccm.toClass();
proxy = (Proxy) pc.newInstance();
} //...省略部分代码
}
return proxy;
}
///http://daveztong.github.io/2016/11/23/Dubbo%E5%AD%A6%E4%B9%A0-%E7%90%86%E8%A7%A3%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86/
abstract public Object newInstance(InvocationHandler handler);//newInstance方法大概是上面注释里的样子
public class Proxy0 extends Proxy implements DC {
public Object newInstance(InvocationHandler var1) {
return new proxy0(var1); // (调下面的方法)返回的是DemoService的实例。
}
public Proxy0() {}
}
//给定一个接口比如DemoService,生成代理如下下
public class proxy0 implements DC, DemoService {
public static Method[] methods;
private InvocationHandler handler;
public void sayHi(String var1) {
Object[] var2 = new Object[]{var1};
//这里去调用InvocationHandler逻辑
this.handler.invoke(this, methods[0], var2);
}
public proxy0() {
}
public proxy0(InvocationHandler var1) {
this.handler = var1;
}
}
复制代码
到这里,javasist这种方式生成代理的方式流程基本梳理通了。
下面看下JDK这种方式创建的代理
JdkProxyFactory
public class JdkProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));//常规方式,直接产生代理
}
//设置用jdk的方式
// 服务引用
// 服务暴露
复制代码
好了。到底用哪种方式呢?这里就涉及到两种方案的性能对比了。
这里有duboo作者的测试结果。
http://javatar.iteye.com/blog/814426
复制代码