dubbo学习笔记 五 dubbo-config

来源:互联网 发布:sketchar软件下载 编辑:程序博客网 时间:2024/06/04 18:44

根据上面的路线,我们先来学习下dubbo-config


dubbo-config 分为两部分 dubbo-config-api 和dubbo -config-spring


dubbo-config-api 


这里主要是一些抽象的定义,把配置信息定义为类属性

referenceConfig  为依赖 消费端的配置


serviceConfig 为提供 服务端的配置






dubbo -config-spring

这个模块主要将这些配置信息和springBean 来整合起来, 把配置转化为bean 让用户来使用。在看dubbo是如何巧妙的将spring 融合起来的之前,先简单熟悉下spring生命周期


srping 生命周期



ReferenceBean

继承与ReferenceConfig  这是一个FactoryBean 工厂bean 用来生成不同的bean。关键看getObject方法 跟进去看ReferenceConfig的init

看其如何把远程服务包装成依赖的bean


    private void init() {    if (initialized) {        return;    }    initialized = true;    if (interfaceName == null || interfaceName.length() == 0) {        throw new IllegalStateException("<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 new IllegalStateException(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 = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");        if (userResolveFile.exists()) {        resolveFile = userResolveFile.getAbsolutePath();        }        }        if (resolveFile != null && resolveFile.length() > 0) {        Properties properties = new Properties();        FileInputStream fis = null;        try {            fis = new FileInputStream(new File(resolveFile));properties.load(fis);} catch (IOException e) {throw new IllegalStateException("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("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");        } else {        logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");        }    }        }        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 = new HashMap<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 method found 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);    }





同时也实现了了InitializingBean的afterPropertiesSet接口

    public void afterPropertiesSet() throws Exception {        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 new IllegalStateException("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) {                ApplicationConfig applicationConfig = null;                for (ApplicationConfig config : applicationConfigMap.values()) {                    if (config.isDefault() == null || config.isDefault().booleanValue()) {                        if (applicationConfig != null) {                            throw new IllegalStateException("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 new IllegalStateException("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 new IllegalStateException("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();        }    }


ServiceBean

实现了ApplicationListener 的onApplicationEvent 接口,同时继承ServiceConfig


    public void onApplicationEvent(ApplicationEvent event) {        if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {        if (isDelay() && ! isExported() && ! isUnexported()) {                if (logger.isInfoEnabled()) {                    logger.info("The service ready on spring started. service: " + getInterface());                }                export();            }        }    }

在spring启动加载完毕,执行ContextRefreshedEvent  

同时来看下export,如何把服务发布出去


   private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {        String name = protocolConfig.getName();        if (name == null || name.length() == 0) {            name = "dubbo";        }        String host = protocolConfig.getHost();        if (provider != null && (host == null || host.length() == 0)) {            host = provider.getHost();        }        boolean anyhost = false;        if (NetUtils.isInvalidLocalHost(host)) {            anyhost = true;            try {                host = InetAddress.getLocalHost().getHostAddress();            } catch (UnknownHostException e) {                logger.warn(e.getMessage(), e);            }            if (NetUtils.isInvalidLocalHost(host)) {                if (registryURLs != null && registryURLs.size() > 0) {                    for (URL registryURL : registryURLs) {                        try {                            Socket socket = new Socket();                            try {                                SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());                                socket.connect(addr, 1000);                                host = socket.getLocalAddress().getHostAddress();                                break;                            } finally {                                try {                                    socket.close();                                } catch (Throwable e) {}                            }                        } catch (Exception e) {                            logger.warn(e.getMessage(), e);                        }                    }                }                if (NetUtils.isInvalidLocalHost(host)) {                    host = NetUtils.getLocalHost();                }            }        }        Integer port = protocolConfig.getPort();        if (provider != null && (port == null || port == 0)) {            port = provider.getPort();        }        final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();        if (port == null || port == 0) {            port = defaultPort;        }        if (port == null || port <= 0) {            port = getRandomPort(name);            if (port == null || port < 0) {                port = NetUtils.getAvailablePort(defaultPort);                putRandomPort(name, port);            }            logger.warn("Use random available port(" + port + ") for protocol " + name);        }        Map<String, String> map = new HashMap<String, String>();        if (anyhost) {            map.put(Constants.ANYHOST_KEY, "true");        }        map.put(Constants.SIDE_KEY, Constants.PROVIDER_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()));        }        appendParameters(map, application);        appendParameters(map, module);        appendParameters(map, provider, Constants.DEFAULT_KEY);        appendParameters(map, protocolConfig);        appendParameters(map, this);        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");                    }                }                List<ArgumentConfig> arguments = method.getArguments();                if (arguments != null && arguments.size() > 0) {                    for (ArgumentConfig argument : arguments) {                        //类型自动转换.                        if(argument.getType() != null && argument.getType().length() >0){                            Method[] methods = interfaceClass.getMethods();                            //遍历所有方法                            if(methods != null && methods.length > 0){                                for (int i = 0; i < methods.length; i++) {                                    String methodName = methods[i].getName();                                    //匹配方法名称,获取方法签名.                                    if(methodName.equals(method.getName())){                                        Class<?>[] argtypes = methods[i].getParameterTypes();                                        //一个方法中单个callback                                        if (argument.getIndex() != -1 ){                                            if (argtypes[argument.getIndex()].getName().equals(argument.getType())){                                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());                                            }else {                                                throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType());                                            }                                        } else {                                            //一个方法中多个callback                                            for (int j = 0 ;j<argtypes.length ;j++) {                                                Class<?> argclazz = argtypes[j];                                                if (argclazz.getName().equals(argument.getType())){                                                    appendParameters(map, argument, method.getName() + "." + j);                                                    if (argument.getIndex() != -1 && argument.getIndex() != j){                                                        throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType());                                                    }                                                }                                            }                                        }                                    }                                }                            }                        }else if(argument.getIndex() != -1){                            appendParameters(map, argument, method.getName() + "." + argument.getIndex());                        }else {                            throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");                        }                    }                }            } // end of methods for        }        if (ProtocolUtils.isGeneric(generic)) {            map.put("generic", generic);            map.put("methods", Constants.ANY_VALUE);        } else {            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 method found in service interface " + interfaceClass.getName());                map.put("methods", Constants.ANY_VALUE);            }            else {                map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));            }        }        if (! ConfigUtils.isEmpty(token)) {            if (ConfigUtils.isDefault(token)) {                map.put("token", UUID.randomUUID().toString());            } else {                map.put("token", token);            }        }        if ("injvm".equals(protocolConfig.getName())) {            protocolConfig.setRegister(false);            map.put("notify", "false");        }        // 导出服务        String contextPath = protocolConfig.getContextpath();        if ((contextPath == null || contextPath.length() == 0) && provider != null) {            contextPath = provider.getContextpath();        }        URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)                .hasExtension(url.getProtocol())) {            url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)                    .getExtension(url.getProtocol()).getConfigurator(url).configure(url);        }        String scope = url.getParameter(Constants.SCOPE_KEY);        //配置为none不暴露        if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {            //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {                exportLocal(url);            }            //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露本地服务)            if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){                if (logger.isInfoEnabled()) {                    logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);                }                if (registryURLs != null && registryURLs.size() > 0                        && url.getParameter("register", true)) {                    for (URL registryURL : registryURLs) {                        url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));                        URL monitorUrl = loadMonitor(registryURL);                        if (monitorUrl != null) {                            url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());                        }                        if (logger.isInfoEnabled()) {                            logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);                        }                        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));                        Exporter<?> exporter = protocol.export(invoker);                        exporters.add(exporter);                    }                } else {                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);                    Exporter<?> exporter = protocol.export(invoker);                    exporters.add(exporter);                }            }        }        this.urls.add(url);    }



AnnotationBean

基于注解的bean 如何处理referenceBean和serviceBean的 依赖问题。如何自定义注解,让spring认识呢?





这样基于Service注册的服务,spring就能扫描这些注解,并把这个class初始化为bean了。


Service 实例化化完之后执行 postProcessAfterInitialization  发布服务。

而有依赖Reference的bean, 在实例化之前 执行postProcessBeforeInitialization 实例化bean

shema

用来解析dubbo标签 构造spring bean

public void init() {    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));    }






0 0