20.反射调用是如何优化的?Wrapper的作用是什么?

反编译生成的代码

对于动态代码生成的class可以写出到本地,办法是:

在com.alibaba.dubbo.common.bytecode.ClassGenerator.mCtc这个实例有

javassist.CtClass.writeFile(String)方法,可以在com.alibaba.dubbo.common.bytecode.ClassGenerator.toClass()结束时将生成的class写出到本地。

对于动态代码生成的class可以用procyon反编译器反编译,命令行形式的,JD有点力不从心。

也可以用阿尔特斯等诊断工具导出。

// com.alibaba.dubbo.common.bytecode.ClassGenerator.mCtc
// mCtc.writeFile("d:/")
//D:\002.tools>java -jar procyon-decompiler-0.5.36.jar //d:\com\alibaba\dubbo\common\bytecode\Wrapper0.class
//
// Decompiled by Procyon v0.5.36
//

package com.alibaba.dubbo.common.bytecode;

import java.lang.reflect.InvocationTargetException;
import org.simonme.dubbo.demo.provider.service.HelloService;
import java.util.Map;

public class Wrapper0 extends Wrapper implements ClassGenerator$DC
{
    public static String[] pns;
    public static Map pts;
    public static String[] mns;
    public static String[] dmns;
    public static Class[] mts0;

    public String[] getPropertyNames() {
        return Wrapper0.pns;
    }

    public boolean hasProperty(final String s) {
        return Wrapper0.pts.containsKey(s);
    }

    public Class getPropertyType(final String s) {
        return Wrapper0.pts.get(s);
    }

    public String[] getMethodNames() {
        return Wrapper0.mns;
    }

    public String[] getDeclaredMethodNames() {
        return Wrapper0.dmns;
    }

    public void setPropertyValue(final Object o, final String s, final Object o2) {
        try {
            final HelloService helloService = (HelloService)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
    }

    public Object getPropertyValue(final Object o, final String s) {
        try {
            final HelloService helloService = (HelloService)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
    }

    public Object invokeMethod(final Object o, final String s, final Class[] array, final Object[] array2) throws InvocationTargetException {
        HelloService helloService;
        try {
            helloService = (HelloService)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        try {
            if ("sayHello".equals(s) && array.length == 1) {
                helloService.sayHello((String)array2[0]);
                return null;
            }
        }
        catch (Throwable t2) {
            throw new InvocationTargetException(t2);
        }
        throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(s).append("\" in class org.simonme.dubbo.demo.provider.service.HelloService.").toString());
    }
}

invokeMethod 实现了方法调用

// D:\002.tools>java -jar procyon-decompiler-0.5.36.jar // d:\com\alibaba\dubbo\common\bytecode\Wrapper1.class
//
// Decompiled by Procyon v0.5.36
//

package com.alibaba.dubbo.common.bytecode;

import java.lang.reflect.InvocationTargetException;
import org.simonme.dubbo.demo.provider.service.DepenededService;
import org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl;
import java.util.Map;

public class Wrapper1 extends Wrapper implements ClassGenerator$DC
{
    public static String[] pns;
    public static Map pts;
    public static String[] mns;
    public static String[] dmns;
    public static Class[] mts0;
    public static Class[] mts1;
    public static Class[] mts2;

    public String[] getPropertyNames() {
        return Wrapper1.pns;
    }

    public boolean hasProperty(final String s) {
        return Wrapper1.pts.containsKey(s);
    }

    public Class getPropertyType(final String s) {
        return Wrapper1.pts.get(s);
    }

    public String[] getMethodNames() {
        return Wrapper1.mns;
    }

    public String[] getDeclaredMethodNames() {
        return Wrapper1.dmns;
    }

    public void setPropertyValue(final Object o, final String s, final Object o2) {
        HelloServiceSlowImpl helloServiceSlowImpl;
        try {
            helloServiceSlowImpl = (HelloServiceSlowImpl)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        if (s.equals("depenededService")) {
            helloServiceSlowImpl.setDepenededService((DepenededService)o2);
            return;
        }
        throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
    }

    public Object getPropertyValue(final Object o, final String s) {
        HelloServiceSlowImpl helloServiceSlowImpl;
        try {
            helloServiceSlowImpl = (HelloServiceSlowImpl)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        if (s.equals("depenededService")) {
            return helloServiceSlowImpl.getDepenededService();
        }
        throw new NoSuchPropertyException(new StringBuffer().append("Not found property \"").append(s).append("\" filed or setter method in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
    }

    public Object invokeMethod(final Object o, final String s, final Class[] array, final Object[] array2) throws InvocationTargetException {
        HelloServiceSlowImpl helloServiceSlowImpl;
        try {
            helloServiceSlowImpl = (HelloServiceSlowImpl)o;
        }
        catch (Throwable t) {
            throw new IllegalArgumentException(t);
        }
        try {
            if ("sayHello".equals(s) && array.length == 1) {
                helloServiceSlowImpl.sayHello((String)array2[0]);
                return null;
            }
            if ("getDepenededService".equals(s) && array.length == 0) {
                return helloServiceSlowImpl.getDepenededService();
            }
            if ("setDepenededService".equals(s) && array.length == 1) {
                helloServiceSlowImpl.setDepenededService((DepenededService)array2[0]);
                return null;
            }
        }
        catch (Throwable t2) {
            throw new InvocationTargetException(t2);
        }
        throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(s).append("\" in class org.simonme.dubbo.demo.provider.service.impl.HelloServiceSlowImpl.").toString());
    }
}

解释

wrap的作用 我的理解是将反射(读取字段、调用业务方法) 转成 直接调用,同时以统一的调用接口对外暴露

JavassistProxyFactory.getInvoker

先用Wrapper机制wrapper一下 。 对于生成的Wrapper实例再怎么放到调用链中和其他Invoker实例怎么相互对接并产生作用可以参见《调用链如何构建的?ProtocolFilterWrapper等分析》。

getPropertyValue与setPropertyValue在你的业务服务实现类中如果实例字段,比如依赖其他服务,这个生成的方法就会起作用了,可以参见上面反编译的第二段代码,上面贴了两段反编译的代码对比也是这个目的

顺带说一句,JavassistProxyFactory 除了在其getInvoker对接wrapper机制完成上述事情之外,还通过其getProxy方法结合其父类的getProxy方法将EchoService回声服务自动织入进业务服务实现中。