我是靠谱客的博主 懦弱睫毛,这篇文章主要介绍4.1 dubbo provider启动之Wrapper包装类 详解在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。,现在分享给大家,希望可以做个参考。
在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。
1.初始化接口的wrapper,所有Wrapper都由getWrapper(接口类)获得,命中缓存则获取对应wrapper,未命中则构建。
复制代码
1String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
2.进入getWrapper,未命中缓存进行构建。这里应用了AOP截面构建。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/** * get wrapper. * 获取接口对应的包装类 * @param c Class instance. * @return Wrapper instance(not null). */ 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; } // 查找rapper缓存,未命中则进行初始化 Wrapper ret = WRAPPER_MAP.get(c); if (ret == null) { // 构建Wrapper ret = makeWrapper(c); WRAPPER_MAP.put(c, ret); } return ret; }
3 进入makeWrapper进行包装类构建,有接口和实现等参数封装一个Wrapper0类,里面有一个核心方法:invokeMethod ,此方法包含了接口所有的方法,以方法名区分,每次执行invokemethod都会调用对应的实现类中的方法。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65private static Wrapper makeWrapper(Class<?> c) { if (c.isPrimitive()) { throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); } //接口名==>interface org.apache.dubbo.demo.DemoService String name = c.getName(); // 从三个加载器里面选一个 ClassLoader cl = ClassHelper.getClassLoader(c); // 重写三个主要方法 setPropertyValue,getPropertyValue,invokeMethod 详见3.1 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); }"); // 非常复杂的一堆构建java文件的字符串,就是把源码构建成字符串给类加载器使用。这里忽略字符串如何拼接。。。不占用篇幅。 ........ ........ ........ ........ ........ ........ // 类编号,使之加载成不同的类。例如:wrapper0,wrapper1,wrapper2..... long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); // 源码生成器辅助类(生成源码使用javassist) 详见下面3.2 ClassGenerator cc = ClassGenerator.newInstance(cl); // 类名称==>org.apache.dubbo.common.bytecode.Wrapper0 cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id); // 父类==>Wrapper.class 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 + ";"); } try { // 构建类 详见下面3.3 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()); } // 生成得到的类==>org.apache.dubbo.common.bytecode.Wrapper0 return (Wrapper) wc.newInstance(); } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } finally { cc.release(); ms.clear(); mns.clear(); dmns.clear(); } }
3.1 重写的三个主要方法如下
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public void setPropertyValue(Object o, String n, Object v) { org.apache.dubbo.demo.DemoService w; try { w = ((org.apache.dubbo.demo.DemoService) $1); } catch (Throwable e) { throw new IllegalArgumentException(e); } throw new org.apache.dubbo.common.bytecode.NoSuchPropertyException("Not found property "" + $2 + "" field or setter method in class org.apache.dubbo.demo.DemoService."); } public Object getPropertyValue(Object o, String n) { org.apache.dubbo.demo.DemoService w; try { w = ((org.apache.dubbo.demo.DemoService) $1); } catch (Throwable e) { throw new IllegalArgumentException(e); } throw new org.apache.dubbo.common.bytecode.NoSuchPropertyException("Not found property "" + $2 + "" field or setter method in class org.apache.dubbo.demo.DemoService."); } // 核心逻辑,根据方法名称,生成对应的调用规则 public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException { org.apache.dubbo.demo.DemoService w; try { w = ((org.apache.dubbo.demo.DemoService) $1); } catch (Throwable e) { throw new IllegalArgumentException(e); } try { if ("sayHello".equals($2) && $3.length == 1) { return ($w) w.sayHello((java.lang.String) $4[0]); } } catch (Throwable e) { throw new java.lang.reflect.InvocationTargetException(e); } throw new org.apache.dubbo.common.bytecode.NoSuchMethodException("Not found method "" + $2 + "" in class org.apache.dubbo.demo.DemoService."); }
3.2 ClassGenerator 类生成器
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public final class ClassGenerator { private static final AtomicLong CLASS_NAME_COUNTER = new AtomicLong(0); private static final String SIMPLE_NAME_TAG = "<init>"; private static final Map<ClassLoader, ClassPool> POOL_MAP = new ConcurrentHashMap<ClassLoader, ClassPool>(); //ClassLoader - ClassPool private ClassPool mPool; private CtClass mCtc; private String mClassName; private String mSuperClass; private Set<String> mInterfaces; private List<String> mFields; private List<String> mConstructors; private List<String> mMethods; private Map<String, Method> mCopyMethods; // <method desc,method instance> private Map<String, Constructor<?>> mCopyConstructors; // <constructor desc,constructor instance> private boolean mDefaultConstructor = false; // public static ClassPool getClassPool(ClassLoader loader) { if (loader == null) { return ClassPool.getDefault(); } // pool是javassist的类 ClassPool pool = POOL_MAP.get(loader); if (pool == null) { pool = new ClassPool(true); pool.appendClassPath(new LoaderClassPath(loader)); POOL_MAP.put(loader, pool); } return pool; } }
3.3 生成class的逻辑,包含够着类名,实现的接口,字段名,方法名等一系列参数 最后得到Class
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66public Class<?> toClass(ClassLoader loader, ProtectionDomain pd) { if (mCtc != null) { mCtc.detach(); } long id = CLASS_NAME_COUNTER.getAndIncrement(); try { CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass); if (mClassName == null) { mClassName = (mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers()) ? ClassGenerator.class.getName() : mSuperClass + "$sc") + id; } // 构建类名 mCtc = mPool.makeClass(mClassName); if (mSuperClass != null) { mCtc.setSuperclass(ctcs); } // 实现的接口 mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag. if (mInterfaces != null) { for (String cl : mInterfaces) { mCtc.addInterface(mPool.get(cl)); } } // 包含的字段名 if (mFields != null) { for (String code : mFields) { mCtc.addField(CtField.make(code, mCtc)); } } // 包含的方法名 if (mMethods != null) { for (String code : mMethods) { if (code.charAt(0) == ':') { mCtc.addMethod(CtNewMethod.copy(getCtMethod(mCopyMethods.get(code.substring(1))), code.substring(1, code.indexOf('(')), mCtc, null)); } else { mCtc.addMethod(CtNewMethod.make(code, mCtc)); } } } // 包含构造函数 这个是true if (mDefaultConstructor) { mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc)); } if (mConstructors != null) { for (String code : mConstructors) { if (code.charAt(0) == ':') { mCtc.addConstructor(CtNewConstructor .copy(getCtConstructor(mCopyConstructors.get(code.substring(1))), mCtc, null)); } else { String[] sn = mCtc.getSimpleName().split("\$+"); // inner class name include $. mCtc.addConstructor( CtNewConstructor.make(code.replaceFirst(SIMPLE_NAME_TAG, sn[sn.length - 1]), mCtc)); } } } // 生成Wrapper包装类(主要复写invokeMethod方法,包含发布的类中包含的所有对应的方法 ) return mCtc.toClass(loader, pd); } catch (RuntimeException e) { throw e; } catch (NotFoundException e) { throw new RuntimeException(e.getMessage(), e); } catch (CannotCompileException e) { throw new RuntimeException(e.getMessage(), e); } }
Wrapper这个类可以理解为一堆if...else...,根据声明的接口类,预生成一批分发逻辑进行缓存。比反射用起来更为灵活,但是也因为是动态生成的类,所以更为复杂。针对接口进行自适应实现,可以作为一种热更新的手段。
最后
以上就是懦弱睫毛最近收集整理的关于4.1 dubbo provider启动之Wrapper包装类 详解在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。的全部内容,更多相关4.1内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复