服務提供者初始化過程,即ServiceBean 初始化過程
一、解析配置文件
spring在解析配置文件的過程中,會找到dubbo 命名空間對應的handler,DubboNamespaceHandler

public class DubboNamespaceHandler extends NamespaceHandlerSupport { static { Version.checkDuplicate(DubboNamespaceHandler.class); } 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)); } }
啟動大致流程

流程如下
- spring容器啟動
- ServiceBean初始化
- 事件發布,執行onApplicationEvent,開始執行ServiceBean暴露export操作
- 啟動NettyServer
- 注冊中心服務暴露export
二、ServiceBean執行export
當Spring容器處理完<dubbo:service>標簽后,會在Spring容器中生成一個ServiceBean ,服務的發布也會在ServiceBean中完成。不妨看一下ServiceBean的定義
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware { }
而在Spring初始化完成Bean的組裝,會調用InitializingBean的
afterPropertiesSet方法,在Spring容器加載完成,會接收到事件ContextRefreshedEvent,調用ApplicationListener的
onApplicationEvent方法。
public void afterPropertiesSet() throws Exception { // if (!isDelay()) { // 暴露服務 export(); } }
ServiceBean 實現了ApplicationListener接口,實現onApplicationEvent方法,該方法在spring容器啟動完成后“自動”執行
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(); } } }
public synchronized void export() { // 延時暴露 if (delay != null && delay > 0) { delayExportExecutor.schedule(new Runnable() { public void run() { // 暴露服務 doExport(); } }, delay, TimeUnit.MILLISECONDS); } else { // 直接暴露服務 doExport(); } }
protected synchronized void doExport() { // checkApplication(); checkRegistry(); checkProtocol(); appendProperties(this); checkStubAndMock(interfaceClass); if (path == null || path.length() == 0) { path = interfaceName; } doExportUrls(); }
private void doExportUrls() { List<URL> registryURLs = loadRegistries(true); for (ProtocolConfig protocolConfig : protocols) { doExportUrlsFor1Protocol(protocolConfig, registryURLs); } }
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) { //如果不是remote,則暴露本地服務 if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) { exportLocal(url); } // 如果配置不是local則暴露為遠程服務 if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) { // 如果注冊中心地址不為null if (registryURLs != null && registryURLs.size() > 0) { for (URL registryURL : registryURLs) { url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic")); // 忽略不相干的代碼 ... // 通過代理工廠將ref對象轉化成invoker對象 Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); // 代理invoker對象 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); } } }
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { URL url = invoker.getUrl(); //忽略若干代碼 //打開服務 openServer(url); optimizeSerialization(url); return exporter; }
private void openServer(URL url) { String key = url.getAddress(); boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true); //是否server端 if (isServer) { ExchangeServer server = serverMap.get(key); if (server == null) { //如果服務不存在,創建服務 serverMap.put(key, createServer(url)); } else { server.reset(url); } } }
private ExchangeServer createServer(URL url) { //忽略若干代碼 ExchangeServer server; try { server = Exchangers.bind(url, requestHandler); } catch (RemotingException e) { throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e); } return server; }
生成的Adpative
import com.alibaba.dubbo.common.extension.ExtensionLoader; public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol { public void destroy() { // 拋出異常,省略 } public int getDefaultPort() { // 拋出異常,省略 } // export public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws RpcException { if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null"); com.alibaba.dubbo.common.URL url = arg0.getUrl(); String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])"); Protocol extension = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName); return extension.export(arg0); } public Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws RpcException { if (arg1 == null) throw new IllegalArgumentException("url == null"); com.alibaba.dubbo.common.URL url = arg1; String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() ); if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])"); Protocol extension = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName); return extension.refer(arg0, arg1); } }