我是靠谱客的博主 懦弱睫毛,这篇文章主要介绍4.1 dubbo provider启动之Wrapper包装类 详解在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。,现在分享给大家,希望可以做个参考。

在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。

 

1.初始化接口的wrapper,所有Wrapper都由getWrapper(接口类)获得,命中缓存则获取对应wrapper,未命中则构建。

复制代码
1
String[] 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
65
private 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
35
public 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
30
public 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
66
public 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内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部