上一篇我们看到dubbo-config-api --> ServiceConfig.java --> doExportUrlsFor1Protocol()方法中有这么一段代码先通过代理工程创建invoker代理,然后将代理暴露为远程服务。
// 代理工厂创建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。我们一次分析这四个类的功能和作用。
Invoker:首先invoker继承自Node接口,该接口中仅有三个接口方法
public interface Node {
/**
* get url.
*
* @return url.
*/
URL getUrl();
/**
* is available.
*
* @return available.
*/
boolean isAvailable();
/**
* destroy.
*/
void destroy();
}
invoker接口中声明了两个方法
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。
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反射更快的操作字节码方法)。
ProxyFactory:代理接口
@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方法。
我们看一下通过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.