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

来源:互联网 发布:电脑网络摄像头 编辑:程序博客网 时间:2024/06/03 18:50

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

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


如果在代码中使用

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

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


如果在代码中使用       

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

可以看到className是com.alibaba.dubbo.config.spring.ReferenceBean。

 

dubbo在spring配置文件中的配置可以是这样的:

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

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

DubboNamespaceHandler类是这样的

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的定义是这样的:

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();    }}