dubbo 创建服务代理

AbstractProxyFactory

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

 

 

 

你可能感兴趣的:(秒扒Dubbo)