前言
或许我们已悉知Java的动态代理的方式:jdk——通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;cglib——通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理。dubbo在沿用java的jdk方式外,还采取了javassist方式——通过字节码生成代替反射。
Dubbo代理概览
类图(这里只包括我们比较常用的代理类)
从类图我们可以看出Dubbo代理工厂主要实现了JavassistProxyFactory和JdkProxyFactory。
具体实现
我们先来看看ProxyFactory接口
@SPI("javassist")
public interface ProxyFactory {
/**
* create proxy.
*
* @param invoker
* @return proxy
*/
@Adaptive({Constants.PROXY_KEY})
<T> T getProxy(Invoker<T> invoker) throws RpcException;
/**
* create proxy.
*
* @param invoker
* @return proxy
*/
@Adaptive({Constants.PROXY_KEY})
<T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;
/**
* create invoker.
*
* @param <T>
* @param proxy
* @param type
* @param url
* @return invoker
*/
@Adaptive({Constants.PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
@SPI(“javassist”)注解表示Dubbo默认使用的代理模式,对应后面将会讲到的JavassistProxyFactory。
@Adaptive({Constants.PROXY_KEY})配合@SPI一起使用,其中{Constants.PROXY_KEY}匹配请求url中参数key值,在ExtensionLoader动态加载扩展进行相应匹配。其详细讲解可参考博文https://blog.csdn.net/matthew_zhang/article/details/68966051
ProxyFactory接口有三个方法声明:
- T getProxy(Invoker invoker):获取代理对象方法接口。
- T getProxy(Invoker invoker, boolean generic):作用与前一个接口相同,多了一个generic参数,这个参数在dubbo:reference中配置,表示是否缺省泛化接口。如果为泛化接口,将返回GenericService,此时消费者可用如下方式调用。
GenericService demoService = (GenericService) context.getBean("demoService");
Object result = demoService.$invoke("getPermissions", new String[] { "java.lang.Long" }, new Object[]{ 1L });
- Invoker getInvoker(T proxy, Class type, URL url):获取调用者方法接口。
继续看AbstractProxyFactory抽象类
public abstract class AbstractProxyFactory implements ProxyFactory {
@Override
public <T> T getProxy(Invoker<T> invoker) throws RpcException {
return getProxy(invoker, false);
}
@Override
public <T> T getProxy(Invoker&l