上一篇咱们看到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.