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)的主要内容,如果未能解决你的问题,请参考以下文章