dubbo源碼:provider發佈service服務二

    上一篇咱們看到dubbo-config-api --> ServiceConfig.java --> doExportUrlsFor1Protocol()方法中有這麼一段代碼先經過代理工程建立invoker代理,而後將代理暴露爲遠程服務。java

// 代理工廠建立invoker,服務代理,經過該代理進行遠程調用
Invoker<?> invoker = proxyFactory.getInvoker(ref,
		(Class) interfaceClass, registryURL
				.addParameterAndEncoded(
						Constants.EXPORT_KEY,
						url.toFullString()));
// 暴露遠程服務
Exporter<?> exporter = protocol.export(invoker);
exporters.add(exporter);

    從上面代碼咱們能夠看到有四個比較關鍵的代碼invoker、proxyFactory、exporter、protocol。咱們一次分析這四個類的功能和做用。api

Invoker:首先invoker繼承自Node接口,該接口中僅有三個接口方法app

public interface Node {

    /**
     * get url.
     * 
     * @return url.
     */
    URL getUrl();
    
    /**
     * is available.
     * 
     * @return available.
     */
    boolean isAvailable();

    /**
     * destroy.
     */
    void destroy();

}

invoker接口中聲明瞭兩個方法ide

public interface Invoker<T> extends Node {

    /**
     * get service interface.
     * 
     * @return service interface.
     */
    Class<T> getInterface();

    /**
     * invoke.
     * 遠程調用工程的具體表示形式
     * @param invocation 調用過程的抽象,若是是RPC調用invocation具體實現就是RpcInvocation
     * @return result
     * @throws RpcException
     */
    Result invoke(Invocation invocation) throws RpcException;

}

invoker接口有多個抽象類以及實現類,這裏咱們暫時只關注含有代理的抽象類AbstractProxyInvoker。ui

public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
    
    private final T proxy;
    
    private final Class<T> type;
    
    private final URL url;

    public AbstractProxyInvoker(T proxy, Class<T> type, URL url){
        if (proxy == null) {
            throw new IllegalArgumentException("proxy == null");
        }
        if (type == null) {
            throw new IllegalArgumentException("interface == null");
        }
        if (! type.isInstance(proxy)) {
            throw new IllegalArgumentException(proxy.getClass().getName() + " not implement interface " + type);
        }
        this.proxy = proxy;
        this.type = type;
        this.url = url;
    }

    public Class<T> getInterface() {
        return type;
    }

    public URL getUrl() {
        return url;
    }

    public boolean isAvailable() {
        return true;
    }

    public void destroy() {
    }

    //業務調用入口方法,在該方法中調用子類中實現的doInvoke方法。
    public Result invoke(Invocation invocation) throws RpcException {
        try {
            return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
        } catch (InvocationTargetException e) {
            return new RpcResult(e.getTargetException());
        } catch (Throwable e) {
            throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
    //子類實現該方法,在子類的該方法中調用代理類的業務代理方法
    protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;

    @Override
    public String toString() {
        return getInterface() + " -> " + getUrl()==null?" ":getUrl().toString();
    }

}

到此咱們基本知道invoker在其中起到的什麼做用了,對業務代理方法再次進行了封裝。接下來咱們繼續看proxyFactory實現。該部分的實如今rpc模塊dubbo-rpc-api工程裏面,ProxyFactory代理工廠接口裏面有兩個方法定義getProxy(Invoker<T> invoker),getInvoker(T proxy, Class<T> type, URL url)前者是經過invoker獲取代理後者是經過代理獲取invoker,服務發佈模塊咱們先看getInvoker方法。ProxyFactory接口的最終實現類有兩個JavassistProxyFactory、JdkProxyFactory主要區別在於生成動態代理的方式不一樣(Javassist提供了比java反射更快的操做字節碼方法)。this

ProxyFactory:代理接口url

@SPI("javassist")
public interface ProxyFactory {

    /**
     * create proxy.
     * 
     * @param invoker
     * @return proxy
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker) throws RpcException;

    /**
     * create invoker.
     * 
     * @param <T>
     * @param proxy
     * @param type
     * @param url
     * @return invoker
     */
    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;

}

該接口還有一個抽象方法,不過該抽象方法並未對getInvoker方法作任何處理。getInvoker的實如今最終實現類裏面。這裏咱們看一下JavassistProxyFactory實現方式。代理

public class JavassistProxyFactory extends AbstractProxyFactory {

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper類不能正確處理帶$的類名,這裏經過Javassist方式建立動態包裝類,主要包含對屬性的get/set方法和invokeMethod方法,在invokeMethod發放中真正調用業務方法
        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);
            }
        };
    }

}

該工廠方法是獲取Invoker對象,首先建立包裝類wrapper,而後再建立代理invoker對象(proxyInvoker),在invoker中實現doInvoker方法調用包裝類中構造的invokerMethod方法,而invokerMethod中調用的則是真實的業務service方法。code

咱們看一下經過Javassist方式生成動態包裝類的實現對象

public static Wrapper getWrapper(Class<?> c)
    {
		
        while( ClassGenerator.isDynamicClass(c) ) // can not wrapper on dynamic class.
            c = c.getSuperclass();

        if( c == Object.class )
            return OBJECT_WRAPPER;//若是是object對象返回基本的包裝類Wrapper

        Wrapper ret = WRAPPER_MAP.get(c);//根據類class衝map中取,若是不存在建立而後放入map中
        if( ret == null )
        {
            ret = makeWrapper(c);//map中不存在,建立包裝類
            WRAPPER_MAP.put(c,ret);
        }
        return ret;
    }

在makeWrapper方法中動態建立包裝類

private static Wrapper makeWrapper(Class<?> c)
	{
		if( c.isPrimitive() )//判斷是否爲基本類型
			throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);

		String name = c.getName();//業務service類名
		ClassLoader cl = ClassHelper.getClassLoader(c);//獲取類加載器

		//拼裝對象屬性設置方法
		StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
		//拼裝對象屬性獲取方法
		StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
		//拼裝對象業務方法調用方法
		StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");

		c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
		c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
		c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");

		Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
		Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
		List<String> mns = new ArrayList<String>(); // method names.
		List<String> dmns = new ArrayList<String>(); // declaring method names.
		
		// get all public field.
		for( Field f : c.getFields() )
		{
			String fn = f.getName();
			Class<?> ft = f.getType();
			if( Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()) )//判斷屬性值爲靜態值或者沒必要進行串行化
				continue;

			c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
			c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");//$w返回一個包裝類型,若是不是包裝類型則忽略
			pts.put(fn, ft);
		}
		
		Method[] methods = c.getMethods();
		// get all public method.
		boolean hasMethod = hasMethods(methods);
		if( hasMethod ){
		    c3.append(" try{");
		}
		for( Method m : methods )
		{
			if( m.getDeclaringClass() == Object.class ) //ignore Object's method.
				continue;

			String mn = m.getName();
			c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");//根據方法名稱以及參數個數找到要執行的方法
            int len = m.getParameterTypes().length;
            c3.append(" && ").append(" $3.length == ").append(len);
			
			boolean override = false;
			for( Method m2 : methods ) {
				if (m != m2 && m.getName().equals(m2.getName())) {//判斷是否有重載方法
					override = true;
					break;
				}
			}
			if (override) {
				if (len > 0) {
					for (int l = 0; l < len; l ++) {
						c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
							.append(m.getParameterTypes()[l].getName()).append("\")");
					}
				}
			}
			
			c3.append(" ) { ");
			
			if( m.getReturnType() == Void.TYPE )//參數爲空時拼裝
				c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");//,調用w。方法(轉化參數)返回null
			else
				c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");//在方法中拼裝object對n方法名調用

			c3.append(" }");
			
			mns.add(mn);//全部方法名稱
			if( m.getDeclaringClass() == c )
				dmns.add(mn);//在c類裏面聲明的方法
			ms.put(ReflectUtils.getDesc(m), m);//全部方法
		}
		if( hasMethod ){
		    c3.append(" } catch(Throwable e) { " );
		    c3.append("     throw new java.lang.reflect.InvocationTargetException(e); " );
	        c3.append(" }");
        }
		
		c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
		//------------------至此成員變量的賦值和取值方法完成,在invokeMethod方法內部完成傳入對象和方法名以及參數信息對該方法調用---------------------------//
		// deal with get/set method.
		Matcher matcher;
		for( Map.Entry<String,Method> entry : ms.entrySet() )
		{
			String md = entry.getKey();
			Method method = (Method)entry.getValue();
			if( ( matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				String pn = propertyName(matcher.group(1));
				c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
				pts.put(pn, method.getReturnType());
			}
			else if( ( matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				String pn = propertyName(matcher.group(1));
				c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
				pts.put(pn, method.getReturnType());
			}
			else if( ( matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() )
			{
				Class<?> pt = method.getParameterTypes()[0];
				String pn = propertyName(matcher.group(1));
				c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt,"$3")).append("); return; }");
				pts.put(pn, pt);
			}
		}
		c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
		c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");

		// make class
		long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
		ClassGenerator cc = ClassGenerator.newInstance(cl);
		cc.setClassName( ( Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw" ) + id );//若是c爲public修飾的類,類名爲Wrapper,若是不是c類名加上$sw1
		cc.setSuperClass(Wrapper.class);

		cc.addDefaultConstructor();
		cc.addField("public static String[] pns;"); // property name array.
		cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
		cc.addField("public static String[] mns;"); // all method name array.
		cc.addField("public static String[] dmns;"); // declared method name array.
		for(int i=0,len=ms.size();i<len;i++)
			cc.addField("public static Class[] mts" + i + ";");

		cc.addMethod("public String[] getPropertyNames(){ return pns; }");
		cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
		cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
		cc.addMethod("public String[] getMethodNames(){ return mns; }");
		cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
		cc.addMethod(c1.toString());
		cc.addMethod(c2.toString());
		cc.addMethod(c3.toString());

		try
		{
			Class<?> wc = cc.toClass();
			// setup static field.
			wc.getField("pts").set(null, pts);
			wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
			wc.getField("mns").set(null, mns.toArray(new String[0]));
			wc.getField("dmns").set(null, dmns.toArray(new String[0]));
			int ix = 0;
			for( Method m : ms.values() )
				wc.getField("mts" + ix++).set(null, m.getParameterTypes());
			return (Wrapper)wc.newInstance();//最終返回包裝對象,裏面包含了invokeMethod方法,以及其餘屬性的set、get方法
		}
		catch(RuntimeException e)
		{
			throw e;
		}
		catch(Throwable e)
		{
			throw new RuntimeException(e.getMessage(), e);
		}
		finally
		{
			cc.release();
			ms.clear();
			mns.clear();
			dmns.clear();
		}
	}

省去對對象屬性的操做,拼裝以後的效果以下每次拼裝針對不一樣的業務類

public class WrapperTest {

	// *****此處省略爲業務對象屬性賦值/取值方法

	public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws InvocationTargetException {

		//業務方法接口,含有兩個方法sayHello/sayBeybey,建立代理方法時動態傳入
		DemoService w;
		try {
			w = ((DemoService) o);
		} catch (Throwable e) {
			throw new IllegalArgumentException(e);
		}

		//循環判斷方法名,若是跟提供的類裏面方法名相同,就調用該方法,並傳入參數
		try {
			//這裏獲取sayHello方法參數個數1
			if("sayHello".equals(n)&&p.length == 1){
				//參數爲p/v 依次類名和對象,好比p=[String.class,User.class],v=["ceshi",user]
				return w.sayHello((String)"ceshi",(User)user);
			}
			
			if("sayBeybey".equals(n)&&p.length == 1){
				return w.sayBeybey((String)"ceshi");
			}
		} catch (Throwable e) {
			throw new java.lang.reflect.InvocationTargetException(e);
		}
		 throw new NoSuchMethodException("Not found method "+n+" in class DemoService .");
	}
	
	// *****此處省略爲業務對象屬性賦值/取值方法

}

至此咱們proxyInvoker已經建立成功。在invoker中的doInvoke方法調用wrapper包裝類invokeMethod方法,在包裝類invokeMethod方法中調用真實service業務方法。

invoker.doInvoke --> wrapper.invokeMethod --> service.doservice.

相關文章
相關標籤/搜索