我是靠谱客的博主 懦弱睫毛,最近开发中收集的这篇文章主要介绍4.1 dubbo provider启动之Wrapper包装类 详解在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。
1.初始化接口的wrapper,所有Wrapper都由getWrapper(接口类)获得,命中缓存则获取对应wrapper,未命中则构建。
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
2.进入getWrapper,未命中缓存进行构建。这里应用了AOP截面构建。
/**
* 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都会调用对应的实现类中的方法。
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 重写的三个主要方法如下
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 类生成器
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
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 dubbo provider启动之Wrapper包装类 详解在进入发布者provider初始化过程前,先说明wrapper这个关键的包装类,在各类接口分发调用的时候起至关重要的作用。承接入口调用,分发到对应的包装类的方法里面。所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复