概述
第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链如下图所示
最后
以上就是凶狠冰淇淋为你收集整理的Dubbo源码阅读六:Dubbo动态生成的类第1节 Dubbo动态生成的类第2节 Protocol$Adaptive类第3节 ProxyFactory$Adaptive类第4节 ProxyFactory Extension实例第5节 Wrapper子类第六节 Protocol Extension实例第七节 Filter Active Extension实例的全部内容,希望文章能够帮你解决Dubbo源码阅读六:Dubbo动态生成的类第1节 Dubbo动态生成的类第2节 Protocol$Adaptive类第3节 ProxyFactory$Adaptive类第4节 ProxyFactory Extension实例第5节 Wrapper子类第六节 Protocol Extension实例第七节 Filter Active Extension实例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复