dubbo的consumer代理的生成方式源码

dubbo的consumer只须要在配置文件中配置一个接口的地址,并不须要这个接口有具体的实现类,就能够生成这个接口的代理,经过代理远程调用provider中的方法。html

和JDK还有CGlib不一样,dubbo的consumer生成代理是经过dubbo中的一个com.alibaba.dubbo.common.bytecode.Proxy来生成的,使用了javassist工具来生成代理类的字节码。java


若是在代码中使用spring

Object obj=ApplicationContextUtil.getBean("orderService");

能够发现obj的class并非com.alibaba.dubbo.common.bytecode.Proxy,而是相似com.alibaba.dubbo.common.bytecode.Proxy26这样的(后面的数字不必定是26),这个Proxy26就是最终生成的代理类,他的父类就是Object,可是有对应接口中的方法。app


若是在代码中使用        jvm

Map<String,BeanDefinition> map=ApplicationContextUtil.getBeanDefinitions();
BeanDefinition definition=map.get(service);
String className=definition.getBeanClassName();

能够看到className是com.alibaba.dubbo.config.spring.ReferenceBean。ide

 

dubbo在spring配置文件中的配置能够是这样的:工具

<dubbo:reference id="orderService" interface="test.orderService" protocol="dubbo" check="false"/>

<dubbo >标签是由com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler来解析的。this

DubboNamespaceHandler类是这样的url

packagecom.alibaba.dubbo.config.spring.schema;
 
importcom.alibaba.dubbo.common.Version;
importcom.alibaba.dubbo.config.ApplicationConfig;
importcom.alibaba.dubbo.config.ConsumerConfig;
importcom.alibaba.dubbo.config.ModuleConfig;
importcom.alibaba.dubbo.config.MonitorConfig;
importcom.alibaba.dubbo.config.ProtocolConfig;
importcom.alibaba.dubbo.config.ProviderConfig;
importcom.alibaba.dubbo.config.RegistryConfig;
importcom.alibaba.dubbo.config.spring.AnnotationBean;
importcom.alibaba.dubbo.config.spring.ReferenceBean;
importcom.alibaba.dubbo.config.spring.ServiceBean;
 
importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;
 
/**
 * DubboNamespaceHandler
 *
 * @author william.liangf
 * @export
 */
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
 
    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }
 
    public void init() {
       registerBeanDefinitionParser("application", newDubboBeanDefinitionParser(ApplicationConfig.class, true));
       registerBeanDefinitionParser("module", newDubboBeanDefinitionParser(ModuleConfig.class, true));
       registerBeanDefinitionParser("registry", newDubboBeanDefinitionParser(RegistryConfig.class, true));
       registerBeanDefinitionParser("monitor", newDubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider",new DubboBeanDefinitionParser(ProviderConfig.class, true));
       registerBeanDefinitionParser("consumer", newDubboBeanDefinitionParser(ConsumerConfig.class, true));
       registerBeanDefinitionParser("protocol", newDubboBeanDefinitionParser(ProtocolConfig.class, true));
       registerBeanDefinitionParser("service", newDubboBeanDefinitionParser(ServiceBean.class, true));
       registerBeanDefinitionParser("reference", newDubboBeanDefinitionParser(ReferenceBean.class, false));
       registerBeanDefinitionParser("annotation", newDubboBeanDefinitionParser(AnnotationBean.class, true));
    }
 
}
因此<dubbo:reference>对应的就是com.alibaba.dubbo.config.spring.ReferenceBean

 

ReferenceBean的定义是这样的:spa

public class ReferenceBean<T> extends ReferenceConfig<T>
  implements FactoryBean,ApplicationContextAware, InitializingBean, DisposableBean
ReferenceBean实现了org.springframework.beans.factory.FactoryBean接口,所以ReferenceBean是一个FactoryBean,spring对FactoryBean不会直接构造他的实现类来做为代理类,而是经过FactoryBean的getObject()方法来得到代理类。

ReferenceBean实现了org.springframework.beans.factory.InitializingBean接口,实现了这个接口的类须要实现afterPropertiesSet()方法,而且在初始化结束后调用该方法。dubbo的consumer的代理类也是在这个方法中生成。

 ReferenceBean的afterPropertiesSet()方法是这样的:

@SuppressWarnings({"unchecked"})
    public void afterPropertiesSet() throwsException {
        if (getConsumer() == null) {
            Map<String, ConsumerConfig>consumerConfigMap = applicationContext == null ? null :BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,ConsumerConfig.class, false, false);
            if (consumerConfigMap != null&& consumerConfigMap.size() > 0) {
                ConsumerConfig consumerConfig =null;
                for (ConsumerConfig config :consumerConfigMap.values()) {
                    if (config.isDefault() ==null || config.isDefault().booleanValue()) {
                        if (consumerConfig !=null) {
                            throw newIllegalStateException("Duplicate consumer configs: " + consumerConfig+ " and " + config);
                        }
                        consumerConfig =config;
                    }
                }
                if (consumerConfig != null) {
                   setConsumer(consumerConfig);
                }
            }
        }
        if (getApplication() == null
                && (getConsumer() ==null || getConsumer().getApplication() == null)) {
            Map<String,ApplicationConfig> applicationConfigMap = applicationContext == null ? null: BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,ApplicationConfig.class, false, false);
            if (applicationConfigMap != null&& applicationConfigMap.size() > 0) {
                ApplicationConfigapplicationConfig = null;
                for (ApplicationConfig config :applicationConfigMap.values()) {
                    if (config.isDefault() == null ||config.isDefault().booleanValue()) {
                        if (applicationConfig!= null) {
                            throw newIllegalStateException("Duplicate application configs: " +applicationConfig + " and " + config);
                        }
                        applicationConfig =config;
                    }
                }
                if (applicationConfig != null){
                   setApplication(applicationConfig);
                }
            }
        }
        if (getModule() == null
                && (getConsumer() ==null || getConsumer().getModule() == null)) {
            Map<String, ModuleConfig>moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,ModuleConfig.class, false, false);
            if (moduleConfigMap != null&& moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig =null;
                for (ModuleConfig config :moduleConfigMap.values()) {
                    if (config.isDefault() ==null || config.isDefault().booleanValue()) {
                        if (moduleConfig !=null) {
                            throw newIllegalStateException("Duplicate module configs: " + moduleConfig +" and " + config);
                        }
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                    setModule(moduleConfig);
                }
            }
        }
        if ((getRegistries() == null ||getRegistries().size() == 0)
                && (getConsumer() ==null || getConsumer().getRegistries() == null ||getConsumer().getRegistries().size() == 0)
                && (getApplication() ==null || getApplication().getRegistries() == null ||getApplication().getRegistries().size() == 0)) {
            Map<String, RegistryConfig>registryConfigMap = applicationContext == null ? null :BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,RegistryConfig.class, false, false);
            if (registryConfigMap != null&& registryConfigMap.size() > 0) {
                List<RegistryConfig>registryConfigs = new ArrayList<RegistryConfig>();
                for (RegistryConfig config :registryConfigMap.values()) {
                    if (config.isDefault() ==null || config.isDefault().booleanValue()) {
                       registryConfigs.add(config);
                    }
                }
                if (registryConfigs != null&& registryConfigs.size() > 0) {
                   super.setRegistries(registryConfigs);
                }
            }
        }
        if (getMonitor() == null
                && (getConsumer() ==null || getConsumer().getMonitor() == null)
                && (getApplication() ==null || getApplication().getMonitor() == null)) {
            Map<String, MonitorConfig>monitorConfigMap = applicationContext == null ? null :BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,MonitorConfig.class, false, false);
            if (monitorConfigMap != null&& monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig =null;
                for (MonitorConfig config :monitorConfigMap.values()) {
                    if (config.isDefault() ==null || config.isDefault().booleanValue()) {
                        if (monitorConfig !=null) {
                            throw newIllegalStateException("Duplicate monitor configs: " + monitorConfig +" and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                    setMonitor(monitorConfig);
                }
            }
        }
        Boolean b = isInit();
        if (b == null && getConsumer()!= null) {
            b = getConsumer().isInit();
        }
        if (b != null &&b.booleanValue()) {
            getObject();
        }
}

主要是按照默认的配置初始化了一些属性,最后调用了getObject()方法,获得代理类

 

getObject()方法:

public Object getObject() throws Exception {
    return get();
  }

get()方法在ReferenceBean的父类com.alibaba.dubbo.config.ReferenceConfig中:

public synchronized T get() {
    if (this.destroyed) {
      throw new IllegalStateException("Alreadydestroyed!");
    }
    if (this.ref == null) {
      init();
    }
    return this.ref;
  }
最后调用了init()方法:

private void init() {
        if (initialized) {
            return;
        }
        initialized = true;
        if (interfaceName == null ||interfaceName.length() == 0) {
            throw newIllegalStateException("<dubbo:reference interface=\"\" />interface not allow null!");
        }
        // 获取消费者全局配置
        checkDefault();
        appendProperties(this);
        if (getGeneric() == null &&getConsumer() != null) {
           setGeneric(getConsumer().getGeneric());
        }
        if (ProtocolUtils.isGeneric(getGeneric())){
            interfaceClass =GenericService.class;
        } else {
            try {
                interfaceClass =Class.forName(interfaceName, true, Thread.currentThread()
                        .getContextClassLoader());
            } catch (ClassNotFoundException e){
                throw newIllegalStateException(e.getMessage(), e);
            }
           checkInterfaceAndMethods(interfaceClass, methods);
        }
        String resolve =System.getProperty(interfaceName);
        String resolveFile = null;
        if (resolve == null || resolve.length()== 0) {
            resolveFile =System.getProperty("dubbo.resolve.file");
            if (resolveFile == null ||resolveFile.length() == 0) {
                File userResolveFile = newFile(new File(System.getProperty("user.home")),"dubbo-resolve.properties");
                if (userResolveFile.exists()) {
                    resolveFile =userResolveFile.getAbsolutePath();
                }
            }
            if (resolveFile != null &&resolveFile.length() > 0) {
                Properties properties = newProperties();
                FileInputStream fis = null;
                try {
                    fis = newFileInputStream(new File(resolveFile));
                    properties.load(fis);
                } catch (IOException e) {
                    throw newIllegalStateException("Unload " + resolveFile + ", cause: "+ e.getMessage(), e);
                } finally {
                    try {
                        if (null != fis)fis.close();
                    } catch (IOException e) {
                       logger.warn(e.getMessage(), e);
                    }
                }
                resolve =properties.getProperty(interfaceName);
            }
        }
        if (resolve != null &&resolve.length() > 0) {
            url = resolve;
            if (logger.isWarnEnabled()) {
                if (resolveFile != null&& resolveFile.length() > 0) {
                    logger.warn("Usingdefault dubbo resolve file " + resolveFile + " replace " +interfaceName + "" + resolve + " to p2p invoke remoteservice.");
                } else {
                    logger.warn("Using -D"+ interfaceName + "=" + resolve + " to p2p invoke remoteservice.");
                }
            }
        }
        if (consumer != null) {
            if (application == null) {
                application =consumer.getApplication();
            }
            if (module == null) {
                module = consumer.getModule();
            }
            if (registries == null) {
                registries =consumer.getRegistries();
            }
            if (monitor == null) {
                monitor =consumer.getMonitor();
            }
        }
        if (module != null) {
            if (registries == null) {
                registries =module.getRegistries();
            }
            if (monitor == null) {
                monitor = module.getMonitor();
            }
        }
        if (application != null) {
            if (registries == null) {
                registries =application.getRegistries();
            }
            if (monitor == null) {
                monitor = application.getMonitor();
            }
        }
        checkApplication();
        checkStubAndMock(interfaceClass);
        Map<String, String> map = newHashMap<String, String>();
        Map<Object, Object> attributes =new HashMap<Object, Object>();
        map.put(Constants.SIDE_KEY,Constants.CONSUMER_SIDE);
        map.put(Constants.DUBBO_VERSION_KEY,Version.getVersion());
        map.put(Constants.TIMESTAMP_KEY,String.valueOf(System.currentTimeMillis()));
        if (ConfigUtils.getPid() > 0) {
            map.put(Constants.PID_KEY,String.valueOf(ConfigUtils.getPid()));
        }
        if (!isGeneric()) {
            String revision =Version.getVersion(interfaceClass, version);
            if (revision != null &&revision.length() > 0) {
                map.put("revision",revision);
            }
 
            String[] methods =Wrapper.getWrapper(interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("NO methodfound in service interface " + interfaceClass.getName());
                map.put("methods",Constants.ANY_VALUE);
            } else {
                map.put("methods",StringUtils.join(new HashSet<String>(Arrays.asList(methods)),","));
            }
        }
        map.put(Constants.INTERFACE_KEY,interfaceName);
        appendParameters(map, application);
        appendParameters(map, module);
        appendParameters(map, consumer,Constants.DEFAULT_KEY);
        appendParameters(map, this);
        String prifix =StringUtils.getServiceKey(map);
        if (methods != null &&methods.size() > 0) {
            for (MethodConfig method : methods){
                appendParameters(map, method,method.getName());
                String retryKey =method.getName() + ".retry";
                if (map.containsKey(retryKey)){
                    String retryValue =map.remove(retryKey);
                    if("false".equals(retryValue)) {
                        map.put(method.getName()+ ".retries", "0");
                    }
                }
                appendAttributes(attributes,method, prifix + "." + method.getName());
               checkAndConvertImplicitConfig(method, map, attributes);
            }
        }
        //attributes经过系统context进行存储.
       StaticContext.getSystemContext().putAll(attributes);
        ref = createProxy(map);
}
init()方法把配置文件中的配置项通过判断和拼装,最后全放到了一个map中,最后调用createProxy()方法来生成代理类:

@SuppressWarnings({"unchecked","rawtypes", "deprecation"})
    private T createProxy(Map<String,String> map) {
        URL tmpUrl = new URL("temp","localhost", 0, map);
        final boolean isJvmRefer;
        if (isInjvm() == null) {
            if (url != null &&url.length() > 0) { //指定URL的状况下,不作本地引用
                isJvmRefer = false;
            } else if(InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
                //默认状况下若是本地有服务暴露,则引用本地服务.
                isJvmRefer = true;
            } else {
                isJvmRefer = false;
            }
        } else {
            isJvmRefer =isInjvm().booleanValue();
        }
 
        if (isJvmRefer) {
            URL url = newURL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0,interfaceClass.getName()).addParameters(map);
            invoker = refprotocol.refer(interfaceClass,url);
            if (logger.isInfoEnabled()) {
                logger.info("Using injvmservice " + interfaceClass.getName());
            }
        } else {
            if (url != null &&url.length() > 0) { // 用户指定URL,指定的URL多是对点对直连地址,也多是注册中心URL
                String[] us =Constants.SEMICOLON_SPLIT_PATTERN.split(url);
                if (us != null &&us.length > 0) {
                    for (String u : us) {
                        URL url =URL.valueOf(u);
                        if (url.getPath() ==null || url.getPath().length() == 0) {
                            url =url.setPath(interfaceName);
                        }
                        if(Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                           urls.add(url.addParameterAndEncoded(Constants.REFER_KEY,StringUtils.toQueryString(map)));
                        } else {
                           urls.add(ClusterUtils.mergeUrl(url, map));
                        }
                    }
                }
            } else { // 经过注册中心配置拼装URL
                List<URL> us =loadRegistries(false);
                if (us != null &&us.size() > 0) {
                    for (URL u : us) {
                        URL monitorUrl =loadMonitor(u);
                        if (monitorUrl != null){
                           map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                        }
                       urls.add(u.addParameterAndEncoded(Constants.REFER_KEY,StringUtils.toQueryString(map)));
                    }
                }
                if (urls == null || urls.size()== 0) {
                    throw newIllegalStateException("No such any registry to reference " +interfaceName + " on the consumer " + NetUtils.getLocalHost() +" use dubbo version " + Version.getVersion() + ", please config<dubbo:registry address=\"...\" /> to your springconfig.");
                }
            }
 
            if (urls.size() == 1) {
                invoker =refprotocol.refer(interfaceClass, urls.get(0));
            } else {
                List<Invoker<?>>invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                for (URL url : urls) {
                    invokers.add(refprotocol.refer(interfaceClass,url));
                    if(Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                        registryURL = url; // 用了最后一个registry url
                    }
                }
                if (registryURL != null) { // 有 注册中心协议的URL
                    // 对有注册中心的Cluster 只用AvailableCluster
                    URL u =registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
                    invoker = cluster.join(newStaticDirectory(u, invokers));
                } else { // 不是 注册中心的URL
                    invoker = cluster.join(newStaticDirectory(invokers));
                }
            }
        }
 
        Boolean c = check;
        if (c == null && consumer != null){
            c = consumer.isCheck();
        }
        if (c == null) {
            c = true; // default true
        }
        if (c &&!invoker.isAvailable()) {
            throw newIllegalStateException("Failed to check the status of the service " +interfaceName + ". No provider available for the service " + (group== null ? "" : group + "/") + interfaceName + (version ==null ? "" : ":" + version) + " from the url " +invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() +" use dubbo version " + Version.getVersion());
        }
        if (logger.isInfoEnabled()) {
            logger.info("Refer dubboservice " + interfaceClass.getName() + " from url " +invoker.getUrl());
        }
        // 建立服务代理
        return (T)proxyFactory.getProxy(invoker);
    }

createProxy()方法加载了和注册中心有关的配置,其中还区分了是不是本地jvm的服务,若是本地有服务,那就直接用本地的。

 最后调用proxyFactory.getProxy(this.invoker)方法来生成代理类

proxyFactory是com.alibaba.dubbo.rpc.ProxyFactory接口的实现类,默认由com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory类来实现,他的getProxy()方法来自他的父类com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory:

public <T> TgetProxy(Invoker<T> invoker) throws RpcException {
        Class<?>[] interfaces = null;
        String config = invoker.getUrl().getParameter("interfaces");
        if (config != null &&config.length() > 0) {
            String[] types =Constants.COMMA_SPLIT_PATTERN.split(config);
            if (types != null &&types.length > 0) {
                interfaces = newClass<?>[types.length + 2];
                interfaces[0] =invoker.getInterface();
                interfaces[1] =EchoService.class;
                for (int i = 0; i <types.length; i++) {
                    interfaces[i + 1] =ReflectUtils.forName(types[i]);
                }
            }
        }
        if (interfaces == null) {
            interfaces = newClass<?>[]{invoker.getInterface(), EchoService.class};
        }
        return getProxy(invoker, interfaces);
}

最后的getProxy()方法在AbstractProxyFactory中是个抽象方法,实现的方法在子类JavassistProxyFactory中:

@SuppressWarnings("unchecked")
    public <T> TgetProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T)Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

这里生成了代理类并建立了代理对象,能够在代码中引用,好比这样:

public class OrderController {
    @Autowired
    private OrderService orderService;
    public void testDubboService() throws Exception{
       orderService.selectByOrderId();
    }
}