public T getProxy(Invoker invoker) 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 + 1] = ReflectUtils.forName(types[i]);
}
}
}
if (interfaces == null) {
interfaces = new Class>[] {invoker.getInterface(), EchoService.class};
}
return getProxy(invoker, interfaces);
}
在dubbo中,定义了一个代理工厂接口ProxyFactory,抽象类AbstractProxyFactory实现了它的getProxy方法,由上面的代码可以看出,其主要是将该代理需要实现的接口给确定好,该接口存储在invoker对象的url的interfaces参数中,是一个字符串,用逗号分隔。AbstractProxyFactory有两个实现类:JdkProxyFactory和JavassistProxyFactory。
这里分析JavassistProxyFactory
@SuppressWarnings("unchecked")
public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
Proxy.getProxy(Class>...ics)->getProxy(ClassLoader,ics)
public static Proxy getProxy(ClassLoader cl, Class>... ics)
{
if( ics.length > 65535 )
throw new IllegalArgumentException("interface limit exceeded");
StringBuilder sb = new StringBuilder();
for(int i=0;i tmp = null;
try
{
tmp = Class.forName(itf, false, cl);
}
catch(ClassNotFoundException e)
{}
if( tmp != ics[i] )
throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
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();//用这个long作为生产类的后缀,防止冲突
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 rt = method.getReturnType();//获取返回类型
Class>[] pts = method.getParameterTypes();//获取参数类型
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
for(int j=0;j[]{ InvocationHandler.class }, new Class>[0], "handler=$1;");
ccp.addDefaultConstructor();
Class> clazz = ccp.toClass();
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
// create Proxy class.
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();//创建代理实例对象
}
catch(RuntimeException e)
{
throw e;
}
catch(Exception e)
{
throw new RuntimeException(e.getMessage(), e);
}
finally
{
// release ClassGenerator
if( ccp != null )
ccp.release();
if( ccm != null )
ccm.release();
synchronized( cache )
{
if( proxy == null )
cache.remove(key);
else
cache.put(key, new WeakReference(proxy));
cache.notifyAll();
}
}
return proxy;
}
(1)首先判断代理实现的接口个数不能超过65535。
(2)遍历所有入参接口,以“;”作为分隔符连接,作为缓存的key。
(3)根据key从缓存中查找Proxy,如果有直接返回,否则第一个执行到此的程序 向缓存中放入PendingGenerationMarker,后来的会根据相同的key获取到这个特殊的标志,而处于wait状态。
(4)遍历所有接口,对于非public接口需要设置包名,遍历接口中的所有方法,对每个方法生成一段代码结构如下:
Object[] args= new Object[pts.length];
args[0] = ($w)$1;
args[1] = ($w)$2;
...
Object ret = handler.invoke(this,method,args);
return ret;
(5)设置代理实例的类名:包名.proxy+id
(6)设置field:public static java.lang.reflect.Method[] methods, private InvocationHandler handler
(7)添加带InvocationHandler的构造函数和无参构造函数。
(8)通过创建另一个class,其父类为Proxy,并创建其实例。
(9)cache.notifyAll()唤醒wait的线程。
最后欢迎大家访问我的个人网站:1024s