在服務(本地和遠程)暴露的時候會調用proxyFactory.getInvoker方法java
具體位置:app
會先調用AOP織入的類StubProxyFactoryWrapper#getInvokeride
而後執行JavassistProxyFactory#getInvoker函數
JavassistProxyFactory#getInvoker以下this
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { // getWrapper會生成代理類 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); } }; }
而後進入Wrapper#getWrapper--> Wrapper#makeWrapper, 具體代碼就在這個makeWrapper方法裏面url
例如如今暴露的服務以下:debug
public interface TestService { String getData(String var1); List<String> getList(); }
那麼生成的代理類以下:代理
public class Wrapper0 extends com.alibaba.dubbo.common.bytecode.Wrapper { /** * 屬性名, 屬性類型 */ public static java.util.Map pts = new HashMap<String, Class<?>>(); public static String[] pns = new String[0]; /** * 全部的方法名 */ public static String[] mns = {"getData"}; /** * 本類中的全部方法名 */ public static String[] dmns = {"getData"}; /** * 一個方法中全部的參數類型 mts[n]屬性的個數和方法的個數形同 */ public static Class[] mts0 = {String.class}; public static Class[] mts1 = {List.class}; @Override public String[] getPropertyNames() { return pns; } @Override public boolean hasProperty(String n) { return pts.containsKey(n); } @Override public Class getPropertyType(String n) { return (Class) pts.get(n); } @Override public String[] getMethodNames() { return mns; } @Override public String[] getDeclaredMethodNames() { return dmns; } @Override public void setPropertyValue(Object o, String n, Object v) { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + n + "\" filed or setter method in class per.qiao.service.TestService."); } @Override public Object getPropertyValue(Object o, String n) { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } if (n.equals("list")) { return w.getList(); } throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + n + "\" filed or setter method in class per.qiao.service.TestService."); } /** * 在調用接口時,就時調用的這個方法 @param o 接口實例 @param n 方法名 @param p 參數類型 @param v 參數 */ @Override public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException { per.qiao.service.TestService w; try { w = ((per.qiao.service.TestService) o); } catch (Throwable e) { throw new IllegalArgumentException(e); } try { //這個try範圍內就是你所須要暴露的全部方法 if ("getData".equals(n) && p.length == 1) { return w.getData((java.lang.String) v[0]); } if ("getList".equals(n) && p.length == 0) { return w.getList(); } } catch (Throwable e) { throw new java.lang.reflect.InvocationTargetException(e); } throw new com.alibaba.dubbo.common.bytecode.NoSuchMethodException("Not found method \"" + n + "\" in class per.qiao.service.TestService."); } }
public class CompilerByJavassist { public static void main(String[] args) throws Exception { // ClassPool:CtClass對象的容器 ClassPool pool = ClassPool.getDefault(); // 經過ClassPool生成一個public新類Emp.java CtClass ctClass = pool.makeClass("per.qiao.javassist.Qiao"); // 添加屬性 private String name CtField nameFild = new CtField(pool.getCtClass("java.lang.String"), "name", ctClass); nameFild.setModifiers(Modifier.PRIVATE); ctClass.addField(nameFild); // 其次添加熟悉privtae int age CtField ageField = new CtField(pool.getCtClass("int"), "age", ctClass); ageField.setModifiers(Modifier.PRIVATE); ctClass.addField(ageField); // 爲屬性name和age添加getXXX和setXXX方法 ctClass.addMethod(CtNewMethod.getter("getName", nameFild)); ctClass.addMethod(CtNewMethod.setter("setName", nameFild)); ctClass.addMethod(CtNewMethod.getter("getAge", ageField)); ctClass.addMethod(CtNewMethod.setter("setAge", ageField)); // 添加構造函數 CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, ctClass); // 爲構造函數設置函數體 StringBuffer buffer = new StringBuffer(); buffer.append("{\n").append("name=\"qiaogege\";\n").append("age=25;\n}"); ctConstructor.setBody(buffer.toString()); // 把構造函數添加到新的類中 ctClass.addConstructor(ctConstructor); // 添加自定義方法 public void printInfo {...} CtMethod ctMethod = new CtMethod(CtClass.voidType, "printInfo", new CtClass[] {}, ctClass); // 爲自定義方法設置修飾符 ctMethod.setModifiers(Modifier.PUBLIC); // 爲自定義方法設置函數體 StringBuffer buffer2 = new StringBuffer(); buffer2.append("{\nSystem.out.println(\"begin!\");\n") .append("System.out.println(name);\n") .append("System.out.println(age);\n") .append("System.out.println(\"over!\");\n").append("}"); ctMethod.setBody(buffer2.toString()); ctClass.addMethod(ctMethod); //最好生成一個class Class<?> clazz = ctClass.toClass(); Object obj = clazz.newInstance(); //ctClass.debugWriteFile("E://Qiao.class"); //反射 執行方法 obj.getClass().getMethod("printInfo", new Class[] {}) .invoke(obj, new Object[] {}); ctClass.debugWriteFile("E://Emp.class"); // 把生成的class文件寫入文件 byte[] byteArr = ctClass.toBytecode(); FileOutputStream fos = new FileOutputStream(new File("E://Qiao.class")); fos.write(byteArr); fos.close(); } }
生成的Class文件放入IDEA中反編譯後的結果以下code
public class Qiao { private String name = "qiaogege"; private int age = 25; public String getName() { return this.name; } public void setName(String var1) { this.name = var1; } public int getAge() { return this.age; } public void setAge(int var1) { this.age = var1; } public Qiao() { } public void printInfo() { System.out.println("begin!"); System.out.println(this.name); System.out.println(this.age); System.out.println("over!"); } }
小結:對象
1. Dubbo經過javassist動態生成一個代理類對象,該對象不一樣於普通的javassist生成的對象,而是隻記錄了暴露接口中的方法的相關參數,生成一個Wrapper類型的對象,並保存在WRAPPER_MAP中,經過invokeMethod方法來執行相應的方法 2. 再將生成的Wrapper對象包裝在AbstractProxyInvoker中進行服務暴露