原理
dubbo根据spring 2.0的schma实现 解析xml并初始化相关bean 初始化dubbo:service为ServiceBean实例 通过spring的生命周期相应回调实现服务发布
ServiceBean源码
/**
* 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();
}
}
/**
* 是否延迟加载
* @return
*/
private boolean isDelay() {
Integer delay = this.getDelay();
ProviderConfig provider = this.getProvider();
if (delay == null && provider != null) {
delay = provider.getDelay();
}
return this.supportedApplicationListener && (delay == null || delay == -1);
}
/**
* 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();
}
}
/**
* DisposableBean实现方法
* @throws Exception
*/
public void destroy() throws Exception {
}
}
ServiceConfig
真正服务发布的方法 以下方法 该方法为继承父类ServiceConfig的方法
if (!this.isDelay()) {
this.export();
}