Dubbo源码学习(三服务暴露ServiceBean)

Posted 皓月行空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo源码学习(三服务暴露ServiceBean)相关的知识,希望对你有一定的参考价值。

坚持一下,把源码看完,勤奋一点,不要在懒惰了,你已经落下别人很多了

环境配置:

jdk  1.7.0.17
dubbo 2.5.x
myeclipse 2014
idea 2017

ServiceBean  是针对<dubbo:service />标签解析封装的config对象,由于ServiceBean 实现了InitializingBean的接口,那么spring在加载bean的时候会调用接口声明的方法afterPropertiesSet,完成bean的初始化工作,如果服务配置了delay>0,则立即暴露服务,调用export方法。除此之外,ServiceBean 还实现了ApplicationListener<ContextRefreshedEvent>接口,当spring的context完成refresh的时候,则会广播event事件,通知所有的Listener进行事件处理,serviceBean在事件处理中也调用了export方法。

ServiceBean

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware


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

public void afterPropertiesSet() throws Exception
        if (getProvider() == null)
            Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
            if (providerConfigMap != null && providerConfigMap.size() > 0)
                Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
                if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
                        && providerConfigMap.size() > 1) // backward compatibility
                    List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
                    for (ProviderConfig config : providerConfigMap.values())
                        if (config.isDefault() != null && config.isDefault().booleanValue())
                            providerConfigs.add(config);
                       
                   
                    if (providerConfigs.size() > 0)
                        setProviders(providerConfigs);
                   
                else
                    ProviderConfig providerConfig = null;
                    for (ProviderConfig config : providerConfigMap.values())
                        if (config.isDefault() == null || config.isDefault().booleanValue())
                            if (providerConfig != null)
                                throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
                           
                            providerConfig = config;
                       
                   
                    if (providerConfig != null)
                        setProvider(providerConfig);
                   
               
           
       
        if (getApplication() == null
                && (getProvider() == null || getProvider().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
                && (getProvider() == null || getProvider().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)
                && (getProvider() == null || getProvider().getRegistries() == null || getProvider().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
                && (getProvider() == null || getProvider().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);
               
           
       
        if ((getProtocols() == null || getProtocols().size() == 0)
                && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0))
            Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
            if (protocolConfigMap != null && protocolConfigMap.size() > 0)
                List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
                for (ProtocolConfig config : protocolConfigMap.values())
                    if (config.isDefault() == null || config.isDefault().booleanValue())
                        protocolConfigs.add(config);
                   
               
                if (protocolConfigs != null && protocolConfigs.size() > 0)
                    super.setProtocols(protocolConfigs);
               
           
       
        if (getPath() == null || getPath().length() == 0)
            if (beanName != null && beanName.length() > 0
                    && getInterface() != null && getInterface().length() > 0
                    && beanName.startsWith(getInterface()))
                setPath(beanName);
           
       
        if (!isDelay())
            export();
       
   

export在ServiceConfig中定义

ServiceConfig.export

    public synchronized void export() 
        if (provider != null) 
            if (export == null) 
                export = provider.getExport();
            
            if (delay == null) 
                delay = provider.getDelay();
            
        
        if (export != null && !export) 
            return;
        

        if (delay != null && delay > 0) 
            delayExportExecutor.schedule(new Runnable() 
                public void run() 
                    doExport();
                
            , delay, TimeUnit.MILLISECONDS);
         else 
            doExport();
        
    

ServiceConfig.doExport精简版

protected synchronized void doExport() 
        if (unexported) 
            throw new IllegalStateException("Already unexported!");
        
        if (exported) 
            return;
        
        exported = true;
        
        checkDefault();
       
        checkApplication();
        checkRegistry();
        checkProtocol();
        appendProperties(this);
        checkStubAndMock(interfaceClass);
        if (path == null || path.length() == 0) 
            path = interfaceName;
        
        doExportUrls();
        ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);
        ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
    
private void doExportUrls() 
        List<URL> registryURLs = loadRegistries(true);
        for (ProtocolConfig protocolConfig : protocols) 
            doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        
    

ServiceConfig.doExportUrlsFor1Protocol精简版

 private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) 
        String name = protocolConfig.getName();
        if (name == null || name.length() == 0) 
            name = "dubbo";
        

        Map<String, String> map = new HashMap<String, String>();
        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);
        





        String scope = url.getParameter(Constants.SCOPE_KEY);
        // don't export when none is configured
        if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) 

            // export to local if the config is not remote (export to remote only when config is remote)
            if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) 
                exportLocal(url);
            
            // export to remote if the config is not local (export to local only when config is 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) 
                    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()));
                        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);

                        Exporter<?> exporter = protocol.export(wrapperInvoker);
                        exporters.add(exporter);
                    
                 else 
                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);

                    Exporter<?> exporter = protocol.export(wrapperInvoker);
                    exporters.add(exporter);
                
            
        
        this.urls.add(url);
    

在方法的最后,不难发现 最终把接口、实现类、注册配置 封装成了invoker对象,并且调用了protocol的export方法把接口暴露出去。

这里的proxyFactory 和protocoldei得单独拿出来讲,因为这里面牵扯到了spi技术,口才有限,说不了太多,所以直接上代码 看起来更好理解一些

以上是关于Dubbo源码学习(三服务暴露ServiceBean)的主要内容,如果未能解决你的问题,请参考以下文章

dubbo源码学习dubbo暴露服务的过程

dubbo学习-服务暴露与注册源码剖析

dubbo源码学习:暴露服务的过程

Dubbo的核心玩法三

Dubbo原理和源码解析之服务暴露

Dubbo原理何源码解析之服务暴露