8. Wrapper.getWrapper Generating Agent Analysis of JavaAssist in Dubbo

Posted by celeb-x2 on Mon, 07 Oct 2019 14:58:34 +0200

1. getWrapper method entry

private void exportLocal(URL url) {
    if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
        URL local = URL.valueOf(url.toFullString())
                .setProtocol(Constants.LOCAL_PROTOCOL)
                .setHost(LOCALHOST)
                .setPort(0);
        ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));
        // Here we call the getInvoker method of proxyFactory, which is an adaptive extension object and defaults to JavassistProxyFactory.
        // So here we go to its getInvoker method.
        Exporter<?> exporter = protocol.export(
                proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
        exporters.add(exporter);
    }
}
// Let's take a look at the specific parameters that are passed in when getInvoker is invoked. See below.
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
    final Wrapper wrapper = 
            Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
            
    return new AbstractProxyInvoker<T>(proxy, type, url) {
        @Override
        protected Object doInvoke(T proxy, String methodName,
                                  Class<?>[] parameterTypes,
                                  Object[] arguments) throws Throwable {
            return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
        }
    };
}

As can be seen from the figure, the incoming proxy is an instance object of DemoService Impl, and the type is a class object of DemoService interface. It can be guessed that the following Wrapper.getWrapper method generates proxy objects for this instance object. The following specific analysis.

2. Generating Wrapper classes

public static Wrapper getWrapper(Class<?> c) {
    while (ClassGenerator.isDynamicClass(c))
        c = c.getSuperclass();

    if (c == Object.class)
        return OBJECT_WRAPPER;

    // Cache function
    Wrapper ret = WRAPPER_MAP.get(c);
    if (ret == null) {
        // Generating Wrapper classes, this logic is difficult to understand, the following first through arthas to generate specific Wrapper classes to observe
        ret = makeWrapper(c);
        WRAPPER_MAP.put(c, ret);
    }
    return ret;
}

The above-mentioned Wrapper (c) method generates a specific Wrapper class, where the code is relatively long, and it builds the Class through javassist. First, what is the Wrapper class generated by Ali's open source arthas tool? Arthas User Document . First start the Provider service provider program, place the breakpoint in ret = makerWrapper(c), make sure that C here is DemoService Impl, and then run the program to the next step to observe the name of ret. Following chart


You can find that the generated Wrapper class is called Wrapper1, and then open the breakpoint to let the program go and the service provider is running. The following figure shows what the generated Wrapper1 is through Arthas. First, download its jar package. Download address.

Topics: Java