原理
dubbo根据spring 2.0的schma实现 解析xml并初始化相关bean 初始化dubbo:service为ServiceBean实例 通过spring的生命周期相应回调实现服务发布
ServiceBean源码
import com.alibaba.dubbo.config.*; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.support.AbstractApplicationContext; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; /** * InitializingBean * 1.初始化的时候会调用afterPropertiesSet方法 * 2.优先级高于init-method * 3.如果afterPropertiesSet出现异常 则不调用init-method * DisposableBean * 1.当调用context.close的时候会执行destroy * ApplicationContextAware * 1.初始化对象会传入spring上下文容器 * ApplicationListener事件 * 1.ContextRefreshedEvent * ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。 * 此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用 * 2.ContextStartedEvent * 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。 * 你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序 * 3.ContextStoppedEvent * 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作 * 4.ContextClosedEvent * 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启 * 5.RequestHandledEvent * 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。 * 在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件 * @param <T> */ class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware { /** * ApplicationContextAware接口实现方法 * @param applicationContext */ public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); if (applicationContext != null) { SPRING_CONTEXT = applicationContext; try { Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class); method.invoke(applicationContext, this); this.supportedApplicationListener = true; } catch (Throwable var5) { if (applicationContext instanceof AbstractApplicationContext) { try { Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class); if (!method.isAccessible()) { method.setAccessible(true); } method.invoke(applicationContext, this); this.supportedApplicationListener = true; } catch (Throwable var4) { ; } } } } } /** * BeanNameAware 接口实现方法 * @param name */ public void setBeanName(String name) { this.beanName = name; } /** * ApplicationListener实现方法 * ContextRefreshedEvent bean被装载则会调用 * @param event */ public void onApplicationEvent(ContextRefreshedEvent event) { if (this.isDelay() && !this.isExported() && !this.isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + this.getInterface()); } this.export(); } } /** * InitializingBean * 实现方法 * @throws Exception */ public void afterPropertiesSet() throws Exception { Map providerConfigMap; /** * step1 * dubbo:servie未指定provider * <dubbo:provider id="test1" delay="-1" retries="0" /> * <dubbo:service provider="test1" interface="com.biz.soa.service.seckill.frontend.SoaSeckillFrontService" ref="soaSeckillFrontServiceImpl"/> */ if (this.getProvider() == null) { /** * step2 * BeanFactoryUtils.beansOfTypeIncludingAncestors为获取指定类型以及实现类和子类的集合 key为name */ providerConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ProviderConfig.class, false, false); /** * 这里面代码逻辑是混乱的 主要看下面分支吧 */ if (providerConfigMap != null && providerConfigMap.size() > 0) { Map<String, ProtocolConfig> protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ProtocolConfig.class, false, false); Iterator i$; ProviderConfig config; /** */ if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && protocolConfigMap.size() > 1) { List<ProviderConfig> providerConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); while(i$.hasNext()) { config = (ProviderConfig)i$.next(); if (config.isDefault() != null && config.isDefault()) { providerConfigs.add(config); } } if (!providerConfigs.isEmpty()) { this.setProviders(providerConfigs); } } else { ProviderConfig providerConfig = null; i$ = protocolConfigMap.values().iterator(); label318: /** * step4 * 这里面需要注意 要么default为true的放到第一个 要么 非default设置为false 没有缺省值 会报Duplicate provider configs * <dubbo:provider id="test1" delay="-1" retries="0" /> * <dubbo:provider id="test2" default="true" delay="-1" retries="0" /> */ while(true) { do { if (!i$.hasNext()) { if (providerConfig != null) { this.setProvider(providerConfig); } break label318; } config = (ProviderConfig)i$.next(); //以上面数据为列 默认null 结束循环 whlie(true) 第二次进来providerConfig不为空 就会报duplicate异常 } while(config.isDefault() != null && !config.isDefault()); if (providerConfig != null) { throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config); } providerConfig = config; } } } } Iterator i$; /** * 跟上面逻辑一样 只是是读取application标签 * <dubbo:application name="soa-promotion-provider"/> */ if (this.getApplication() == null && (this.getProvider() == null || this.getProvider().getApplication() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ApplicationConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; i$ = protocolConfigMap.values().iterator(); label291: while(true) { ApplicationConfig config; do { if (!i$.hasNext()) { if (applicationConfig != null) { this.setApplication(applicationConfig); } break label291; } config = (ApplicationConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } } /** * 跟上面一样 读取moudule标签 * <dubbo:module name="soa-promotion-provider" version="1.0" owner="liqianng" organization="信息部"></dubbo:module> */ if (this.getModule() == null && (this.getProvider() == null || this.getProvider().getModule() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ModuleConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { ModuleConfig moduleConfig = null; i$ = protocolConfigMap.values().iterator(); label270: while(true) { ModuleConfig config; do { if (!i$.hasNext()) { if (moduleConfig != null) { this.setModule(moduleConfig); } break label270; } config = (ModuleConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } } ArrayList protocolConfigs; /** * 同上 * <dubbo:registry address="${zookeeper.url}" file=".dubbo/promotion-provider.cache" check="false" /> */ if ((this.getRegistries() == null || this.getRegistries().isEmpty()) && (this.getProvider() == null || this.getProvider().getRegistries() == null || this.getProvider().getRegistries().isEmpty()) && (this.getApplication() == null || this.getApplication().getRegistries() == null || this.getApplication().getRegistries().isEmpty())) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, RegistryConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { protocolConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); label240: while(true) { RegistryConfig config; do { if (!i$.hasNext()) { if (protocolConfigs != null && !protocolConfigs.isEmpty()) { super.setRegistries(protocolConfigs); } break label240; } config = (RegistryConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); protocolConfigs.add(config); } } } /** * //表示从注册中心发现监控地址 * <dubbo:monitor protocol="registry"></dubbo:monitor> */ if (this.getMonitor() == null && (this.getProvider() == null || this.getProvider().getMonitor() == null) && (this.getApplication() == null || this.getApplication().getMonitor() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, MonitorConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { MonitorConfig monitorConfig = null; i$ = protocolConfigMap.values().iterator(); label215: while(true) { MonitorConfig config; do { if (!i$.hasNext()) { if (monitorConfig != null) { this.setMonitor(monitorConfig); } break label215; } config = (MonitorConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } } /** * 获取配置的协议信息 * <dubbo:protocol register="false" name="dubbo" port="23888" threadpool="fixed" threads="500" dispatcher="message"/> * */ if ((this.getProtocols() == null || this.getProtocols().isEmpty()) && (this.getProvider() == null || this.getProvider().getProtocols() == null || this.getProvider().getProtocols().isEmpty())) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { protocolConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); label190: while(true) { ProtocolConfig config; do { if (!i$.hasNext()) { if (protocolConfigs != null && !protocolConfigs.isEmpty()) { super.setProtocols(protocolConfigs); } break label190; } config = (ProtocolConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); protocolConfigs.add(config); } } } if ((this.getPath() == null || this.getPath().length() == 0) && this.beanName != null && this.beanName.length() > 0 && this.getInterface() != null && this.getInterface().length() > 0 && this.beanName.startsWith(this.getInterface())) { this.setPath(this.beanName); } /** * 是否延迟注册服务 默认为0 以毫秒为单位 */ if (!this.isDelay()) { this.export(); } } /** * 是否延迟加载 * @return */ private boolean isDelay() { //从当前service标签获取 Integer delay = this.getDelay(); ProviderConfig provider = this.getProvider(); //如果没有设置则从provider标签获取 if (delay == null && provider != null) { delay = provider.getDelay(); } return this.supportedApplicationListener && (delay == null || delay == -1); } /** * DisposableBean实现方法 * @throws Exception */ public void destroy() throws Exception { } }
ServiceConfig
真正服务发布的方法 以下方法 该方法为继承父类ServiceConfig的方法
if (!this.isDelay()) { this.export(); }