dubbo 创建服务代理

AbstractProxyFactory

public <T> T getProxy(Invoker<T> 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> T getProxy(Invoker<T> 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<ics.length;i++)//遍历所有入参接口,以“;”作为分隔符连接
		{
			String itf = ics[i].getName();
			if( !ics[i].isInterface() )
				throw new RuntimeException(itf + " is not a interface.");

			Class<?> 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<String, Object> cache;
		synchronized( ProxyCacheMap )
		{
			cache = ProxyCacheMap.get(cl);
			if( cache == null )
		    {
				cache = new HashMap<String, Object>();
				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<String> worked = new HashSet<String>();
			List<Method> methods = new ArrayList<Method>();

			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++)//构建方法体,其实现是委托给InvokerInvocationhandler实例对象
						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;

			// create ProxyInstance class.
			String pcn = pkg + ".proxy" + id;//类名为名名+“.proxy”+自增数值
			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]));

			// 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>(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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值