二Dubbo设计基础--2Wrapper

二Dubbo设计基础--2Wrapper

2.2 Dubbo中Wrapper

注意,区别Dubbo中Wrapper.getWrapper和wrapper机制。前者用在provider端构造invoker时,javassist字节码方式,构建字节码——>>class对象——>>反射创建实例,构造目标服务类的proxy代理对象;

后者是用在SPI获取自动拓展时,为拓展类增加wrapper包裹得到的XXXWrapper类,是dubbo中AOP功能的实现。

2.2.1 Wrapper.getWrapper

2.2.1.1 Wrapper类

Wapper是一个包装类。主要用于“包裹”目标类,仅可以通过getWapper(Class)方法创建子类。在创建子类过程中,子类代码会对传进来的Class对象进行解析,拿到类方法,类成员变量等信息。而这个包装类持有实际的扩展点实现类。也可以把扩展点的公共逻辑全部移到包装类中,功能上就是作为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;

        Wrapper ret = WRAPPER_MAP.get(c);
        if (ret == null) {
            ret = makeWrapper(c);
            WRAPPER_MAP.put(c, ret);
        }
        return ret;
    }

wrapper.getWrapper生成的类,把目标类所有方法,全部放在invokeMethod方法中,

invoker.doInvoke(wrapper.invokeMethod);//invoker对provider服务实现类的调用逻辑

调用方法,根据方法名称,从wrapper的invokeMethod内,找到对应的方法执行。

2.2.1.2 wrapper.getWrapper实现

wrapper的创建和使用,详细见[6.3.2.1 Provider端Invoker](#6.3.2.1 Provider端Invoker)

跟入Wrapper源码:

 //传入的参数Class为provider端对外提供服务的service实现类
private static Wrapper makeWrapper(Class<?> c){
  	//如果class为基本类型,抛异常
		if( c.isPrimitive() )
			throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);

		String name = c.getName();
		ClassLoader cl = ClassHelper.getCallerClassLoader(Wrapper.class);
		//存储setPropertyValue属性设置的代码
		StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
  	//存储getPropertyValue获取属性的代码
		StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
  	//存储invokeMethod(调用目标类方法)方法
		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); }");

该处,传入makeWrapper的类为服务实现类serviceImpl。

执行完上面代码,构造的结果如下(构建目标proxy的代码段,可快速大致看)

c3=public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException{ 
  com.alibaba.dubbo.demo.impl.DemoServiceImpl w; 
  try{ 
    //该处就是添加类型转换代码的位置
    w = ((com.alibaba.dubbo.demo.impl.DemoServiceImpl)$1); 
  }catch(Throwable e){ 
    throw new IllegalArgumentException(e); 
  }

继续,

		//存储成员变量name:type
		Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
  	//存储方法name:Method对象
		Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
  	//存储方法names
		List<String> mns = new ArrayList<String>(); // method names.
  	//存储当前类声明的方法names
		List<String> dmns = new ArrayList<String>(); // declaring method names.
		
/** ——————————————————————————————对proxy中属性的处理——————————————————————————————-*/
		// 对service类中属性处理
		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("; }");
			pts.put(fn, ft);
		}
		
/** --——————————————————————proxy内方法处理—————————————————————————————— */
		//proxy服务提供类内method对象(此时包含所有方法,包括object内方法)
		Method[] methods = c.getMethods();
		boolean hasMethod = hasMethods(methods);
		if( hasMethod ){
		    c3.append(" try{");
		}
		for( Method m : methods ){
      //如果声明当前方法的类为,object.class,跳过该方法(不处理object继承的方法)
			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 ) {
        //判定当前m,在method中有没有override方法
				if (m != m2 && m.getName().equals(m2.getName())) {
					override = true;
					break;
				}
			}
      //当m有override方法时
			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(" ) { ");
      
			//当前method返回类型为void时
			if( m.getReturnType() == Void.TYPE )
				c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
			else//当前method返回类型非void
				c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");

			c3.append(" }");
			//mns、dmns维护
			mns.add(mn);
			if( m.getDeclaringClass() == c ) //如果method的声明类,是当前类(表示当前类中声明的方法)
				dmns.add(mn);
			ms.put(ReflectUtils.getDesc(m), m);
		}

此时,针对serviceImpl中getPermission方法,生成的方法(wrapper会把目标类中所有的方法全部放在invokeMethod中。如果多个方法,会再invokeMethod中根据方法名,选择对应的方法调用)。此时构造的字符串如下:

//c3字符串
//第一个参数为provider服务实现类,第二个参数为方法名methodName,第三个为参数类型,第四个为方法参数
public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException{
  com.alibaba.dubbo.demo.impl.DemoServiceImpl w;
  try{ 
    //服务真实实现类
    w = ((com.alibaba.dubbo.demo.impl.DemoServiceImpl)$1); 
  }catch(Throwable e){
    throw new IllegalArgumentException(e); 
  } 
  try{ 
    if( "getPermissions".equals( $2 )  &&  $3.length == 1 ) {  
      //调用服务实现类真实方法
      return ($w)w.getPermissions((java.lang.Long)$4[0]); 
    }

继续,(跳过get、set方法处理,比较常规,可以自行debug跟着代码查看)

		// make class
		long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
		//通过ClassGenerator为上述过程生成的代码,创建class类,然后根据class反射创建对象——javassist生成类
		ClassGenerator cc = ClassGenerator.newInstance(cl);

跟进ClassGenerator类,

public static ClassGenerator newInstance(ClassLoader loader)
	{
		return new ClassGenerator(getClassPool(loader));
	}
	
		//javassist创建字节码的服务类ClassPool
		public static ClassPool getClassPool(ClassLoader loader)
	{
		if( loader == null )
			return ClassPool.getDefault();

		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;
	}

然后继续跟getWrapper,

// make class
		long id = WRAPPER_CLASS_COUNTER.getAndIncrement();//自增id,用来命名wrapper类
		//通过ClassGenerator为上述过程生成的代码,创建class类,然后根据class反射创建对象——javassist生成类
		ClassGenerator cc = ClassGenerator.newInstance(cl);		

    cc.setClassName( ( Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw" ) + id ); //com.alibaba.dubbo.common.bytecode.Wrapper1

		//设置生成包装类的父类
		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
			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());
      //反射创建目标对象proxy的wrapper包装类
			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();
		}
	}
}

上述过程,通过Dubbo自己的ClassGenerator,其初始化通过获取javassist的ClassPool工具类,然后在getWrapper中,对构建的字节码转换为Class对象,然后反射创建实例对象。

2.2.2 Wrapper机制

//todo

posted @ 2023-03-13 14:35  LeasonXue  阅读(50)  评论(0编辑  收藏  举报