Dubbo源码阅读六:Dubbo动态生成的类

第1节 Dubbo动态生成的类

dubbo在调用exportServices()方法时,会使用代码生成技术动态地生成Protocol$Adaptive、ProxyFactory$Adaptive和Wrapper子类这些类。

Dubbo使用javassist动态生成类。Dubbo有两个场景使用动态类。

1)ExtensionLoader.getExtensionLoader().getAdaptiveExtension()使用JavassistCompiler生成每个类型的Adaptive类。Protocol$Adaptive、ProxyFactory$Adaptive等类通过这种方法生成。

2)ServiceConfig.doExportUrlsFor1Protocol()使用JavassistProxyFactory.getInvoker()方法调用Wrapper.makeWrapper()方法,为xml中的<dubbo:service>生成Wrapper子类。

第2节 Protocol$Adaptive类

GreetingService的定义如下。

package org.example.dubbo2.provider.api;
public interface GreetingService {
    String sayHi(String name);
    String sayBye(String name);
}

GreetingServiceImpl的实现如下。

package org.example.dubbe2.provider.impl;
import org.example.dubbo2.provider.api.GreetingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GreetingServiceImpl implements GreetingService {
    private static final Logger logger = LoggerFactory.getLogger(GreetingServiceImpl.class);
    @Override
    public String sayHi(String name) {
        logger.info(name);
        return "hi, " + name;
    }
    @Override
    public String sayBye(String name) {
        logger.info(name);
        return "bye, " + name;
    }
}

启动类如下。

package org.example.dubbe2.provider.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
@Configuration
public class Dubbo2ProviderApplication {
    private static final Logger logger = LoggerFactory.getLogger(Dubbo2ProviderApplication.class);
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"/spring/dubbo-provider.xml"});
        context.start();
        System.in.read(); // 按任意键退出
    }
}

dubbo-provider.xml内容如下。

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    <dubbo:application name="dubbo2-provider"/>
    <dubbo:registry address="zookeeper://172.16.4.126:2181"/>
    <dubbo:metadata-report address="zookeeper://172.16.4.126:2181"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:service interface="org.example.dubbo2.provider.api.GreetingService" ref="greetingService"/>
    <bean id="greetingService" class="org.example.dubbe2.provider.impl.GreetingServiceImpl"/>
</beans>

ServiceConfig的定义如下(去掉了其他信息)。JVM在加载ServiceConfig类时,会初始化他的两个static静态字段。

public class ServiceConfig<T> extends ServiceConfigBase<T> {
    private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
}

在调用ExtensionLoader.getAdaptiveExtension()方法时,会执行createAdaptiveExtensionClass()方法动态生成Protocol$Adaptive和ProxyFactoryAdaptive类。在createAdaptiveExtensionClass()代码中增加断点,启动程序执行到断点处,查看code的值,如下图所示。

将code的值拷贝出来格式化后,动态生成的Protocol$Adaptive类代码如下。

package org.apache.dubbo.rpc;

import org.apache.dubbo.common.extension.ExtensionLoader;

public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
    public void destroy() {
        throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    public int getDefaultPort() {
        throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }

    public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg1;
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.refer(arg0, arg1);
    }

    public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
        org.apache.dubbo.common.URL url = arg0.getUrl();
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
    }

    public java.util.List getServers() {
        throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
    }
}

 

第3节 ProxyFactory$Adaptive类

将code的值拷贝出来格式化后,动态生成的ProxyFactory$Adaptive类代码如下。

package org.apache.dubbo.rpc;

import org.apache.dubbo.common.extension.ExtensionLoader;

public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
    public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {
        if (arg2 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg2;
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getInvoker(arg0, arg1, arg2);
    }

    public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, boolean arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
        org.apache.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getProxy(arg0, arg1);
    }

    public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
        if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
        org.apache.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])");
        org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);
        return extension.getProxy(arg0);
    }
}

第4节 ProxyFactory Extension实例

org.apache.dubbo.rpc.ProxyFactory配置内容如下:

stub=org.apache.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory

这些类都实现了ProxyFacotry接口。

ProxyFactory类的ExtesnionLoader加载器在实例化JavassistProxyFactory对象时,会对JavassistProxyProxyFactory实例加上StubProxyFactoryWrapper装饰,其目的是利用装饰器模式来实现AOP的功能。

第5节 Wrapper子类

在ServiceConfig.doExportUrlsFor1Protocol()方法中调用exportLocal()处增加断点如下图,启动程序执行到这里,然后F7执行进入exportLocal()方法。

执行到PROTOCOL.export(PROXY_FACTORY.getInvoker(ref, interfaceClass, local))。

 

然后F7调用进入JavassistProxFactory.getInvoker()方法。一直往下执行到Wrapper.makeWrapper()方法。

 

在Wrapper.makeWrapper()方法中的cc.toClass()增加断点,运行到此处,然后F7进入ClassGenerator.toClass()方法,接着进入ClassGenerator.toClass(ClassLoader loader, ProtectionDomain pd)方法,一直F8单步运行到return mCtc.toClass(laoder, pd)。

 

 

 

在IDEA中点开Evaluate对话框,在Expression编辑框中输入如下代码,将动态生成的CtClass对象写入本地1.class文件中。

FileOutputStream out1 = new FileOutputStream("D:\\1.class");out1.write(mCtc.toBytecode());out1.close();return "";

 然后找到这个1.class文件,选中后拖入IDEA编辑框,就可以查看到class文件对应的源码内容。

<dubbo:service interface="org.example.dubbo2.provider.api.GreetingService" ref="greetingService"/>
<bean id="greetingService" class="org.example.dubbe2.provider.impl.GreetingServiceImpl"/>

 为xml中以上<dubbo:service>标签生成的动态类如下,是Wrapper类的子类。

package org.apache.dubbo.common.bytecode;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.dubbo.common.bytecode.ClassGenerator.DC;
import org.example.dubbe2.provider.impl.GreetingServiceImpl;

public class Wrapper1 extends Wrapper implements 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 String[] getPropertyNames() {
        return pns;
    }

    public boolean hasProperty(String var1) {
        return pts.containsKey(var1);
    }

    public Class getPropertyType(String var1) {
        return (Class)pts.get(var1);
    }

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

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

    public void setPropertyValue(Object var1, String var2, Object var3) {
        try {
            GreetingServiceImpl var4 = (GreetingServiceImpl)var1;
        } catch (Throwable var6) {
            throw new IllegalArgumentException(var6);
        }

        throw new NoSuchPropertyException("Not found property \"" + var2 + "\" field or setter method in class org.example.dubbe2.provider.impl.GreetingServiceImpl.");
    }

    public Object getPropertyValue(Object var1, String var2) {
        try {
            GreetingServiceImpl var3 = (GreetingServiceImpl)var1;
        } catch (Throwable var5) {
            throw new IllegalArgumentException(var5);
        }

        throw new NoSuchPropertyException("Not found property \"" + var2 + "\" field or getter method in class org.example.dubbe2.provider.impl.GreetingServiceImpl.");
    }

    public Object invokeMethod(Object var1, String var2, Class[] var3, Object[] var4) throws InvocationTargetException {
        GreetingServiceImpl var5;
        try {
            var5 = (GreetingServiceImpl)var1;
        } catch (Throwable var8) {
            throw new IllegalArgumentException(var8);
        }

        try {
            if ("sayHi".equals(var2) && var3.length == 1) {
                return var5.sayHi((String)var4[0]);
            }

            if ("sayBye".equals(var2) && var3.length == 1) {
                return var5.sayBye((String)var4[0]);
            }
        } catch (Throwable var9) {
            throw new InvocationTargetException(var9);
        }

        throw new NoSuchMethodException("Not found method \"" + var2 + "\" in class org.example.dubbe2.provider.impl.GreetingServiceImpl.");
    }

    public Wrapper1() {
    }
}

第六节 Protocol Extension实例

org.apache.dubbo.rpc.Protocol配置内容如下:

filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=org.apache.dubbo.rpc.support.MockProtocol
dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
injvm=org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol
http=org.apache.dubbo.rpc.protocol.http.HttpProtocol
rmi=org.apache.dubbo.rpc.protocol.rmi.RmiProtocol
hessian=org.apache.dubbo.rpc.protocol.hessian.HessianProtocol
webservice=org.apache.dubbo.rpc.protocol.webservice.WebServiceProtocol
thrift=org.apache.dubbo.rpc.protocol.thrift.ThriftProtocol
native-thrift=org.apache.dubbo.rpc.protocol.nativethrift.ThriftProtocol
memcached=org.apache.dubbo.rpc.protocol.memcached.MemcachedProtocol
redis=org.apache.dubbo.rpc.protocol.redis.RedisProtocol
rest=org.apache.dubbo.rpc.protocol.rest.RestProtocol
xmlrpc=org.apache.dubbo.xml.rpc.protocol.xmlrpc.XmlRpcProtocol
grpc=org.apache.dubbo.rpc.protocol.grpc.GrpcProtocol
registry=org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol
service-discovery-registry=org.apache.dubbo.registry.integration.RegistryProtocol
qos=org.apache.dubbo.qos.protocol.QosProtocolWrapper

 这些类都实现了Protocol接口。

ProtocolFilterWrapper、ProtocolListenerWrapper、QosProtocolWrapper是三个装饰器类,用于装饰其他Protocol实例。装饰顺序如下

QosProtocolWrapper
  -> ProtocolFilterWrapper
     -> ProtocolListenerWrapper
       -> 其他Protocol实现类

第七节 Filter Active Extension实例

org.apache.dubbo.rpc.Filter配置内容如下:

cache=org.apache.dubbo.cache.filter.CacheFilter
validation=org.apache.dubbo.validation.filter.ValidationFilter
echo=org.apache.dubbo.rpc.filter.EchoFilter
generic=org.apache.dubbo.rpc.filter.GenericFilter
genericimpl=org.apache.dubbo.rpc.filter.GenericImplFilter
token=org.apache.dubbo.rpc.filter.TokenFilter
accesslog=org.apache.dubbo.rpc.filter.AccessLogFilter
activelimit=org.apache.dubbo.rpc.filter.ActiveLimitFilter
classloader=org.apache.dubbo.rpc.filter.ClassLoaderFilter
context=org.apache.dubbo.rpc.filter.ContextFilter
consumercontext=org.apache.dubbo.rpc.filter.ConsumerContextFilter
exception=org.apache.dubbo.rpc.filter.ExceptionFilter
executelimit=org.apache.dubbo.rpc.filter.ExecuteLimitFilter
deprecated=org.apache.dubbo.rpc.filter.DeprecatedFilter
compatible=org.apache.dubbo.rpc.filter.CompatibleFilter
timeout=org.apache.dubbo.rpc.filter.TimeoutFilter
tps=org.apache.dubbo.rpc.filter.TpsLimitFilter
trace=org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter
future=org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter
monitor=org.apache.dubbo.monitor.support.MonitorFilter

metrics=org.apache.dubbo.monitor.dubbo.MetricsFilter

provider端的Active Filter实例

ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), "service.filter", "provicer")获取到的provider端的有效Filter实例如下:

filters = {ArrayList@4255}  size = 8
 0 = {EchoFilter@5306} 
 1 = {ClassLoaderFilter@5307} 
 2 = {GenericFilter@5308} 
 3 = {ContextFilter@5309} 
 4 = {TraceFilter@5310} 
 5 = {TimeoutFilter@5311} 
 6 = {MonitorFilter@5312} 
 7 = {ExceptionFilter@5313} 

 对invoker进行过滤器链包装,FilterNode链如下图所示

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值