ServiceBean的afterPropertiesSet方法是实现了InitializingBean, 还是准备先做宏观分析, 然后再做细致分析. 下面先宏观分析:
@Override
@SuppressWarnings({"unchecked", "deprecation"})
public void afterPropertiesSet() throws Exception {
if (getProvider() == null) {
// 从IOC容器里面查找实现了 ProviderConfig.class 这个类的类
......
// 获取provider配置
}
if (getApplication() == null && (getProvider() == null || getProvider().getApplication() == null)) {
// ConfigManager类, 用于记录dubbo相关的配置信息
// ConfigManager.getInstance().setApplication(application);
// ServiceBean.getInstance().application = application;
......
// 获取application配置
}
if (getModule() == null && (getProvider() == null || getProvider().getModule() == null)) {
......
// 获取module配置
}
if (StringUtils.isEmpty(getRegistryIds())) {
// ConfigManager类, 用于记录dubbo相关的配置信息
// ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries);
// ServiceBean.getInstance().registries = (List<RegistryConfig>) registries;
......
// 获取注册中心的配置
}
if (CollectionUtils.isEmpty(getProtocols()) && (getProvider() == null || CollectionUtils.isEmpty(getProvider().getProtocols()))) {
// ConfigManager类, 用于记录dubbo相关的配置信息
// ConfigManager.getInstance().addProtocols((List<ProtocolConfig>) protocols);
// ServiceBean.getInstance().protocols = (List<ProtocolConfig>) protocols;
......
// 获取protocol配置
}
// 获取<dubbo:service />的path属性, path即服务的发布路径
if (StringUtils.isEmpty(getPath())) {
if (StringUtils.isNotEmpty(beanName)
&& StringUtils.isNotEmpty(getInterface())
&& beanName.startsWith(getInterface())) {
// ServiceBean.getInstance().path = beanName;
setPath(beanName);
}
}
if (!supportedApplicationListener) {
export();
}
}
通过上面的分析对整个在做什么有了大致的了解, 下面进行细致分析, 对里面的一段段代码分别展开分析:
1. 获取Provider配置
// 当某个<dubbo:service />没有绑定相应的<dubbo:provider/>的时候, 就会触发下面的逻辑
if (getProvider() == null) {
// 在spring的IOC容器中查找所有的type为ProviderConfig.class或其子类的bean, 可能会有多个provider的配置
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
if (providerConfigMap != null && providerConfigMap.size() > 0) {
// 在spring的IOC容器中查找type为ProtocolConfig.class或其子类的bean
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
// 存在<dubbo:provider />但不存在<dubbo:protocol />配置的情况, 也就是说旧版本的protocol配置需要从provider中提取, 兼容旧版本
if (CollectionUtils.isEmptyMap(protocolConfigMap) && providerConfigMap.size() > 1) { // backward compatibility
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
for (ProviderConfig config : providerConfigMap.values()) {
// 当<dubbo:provider default="true" />时, providerConfigs才会加入
if (config.isDefault() != null && config.isDefault()) {
providerConfigs.add(config);
}
}
// 在配置provider的同时, 也从默认的<dubbo:provider />中提取protocol的配置
if (!providerConfigs.isEmpty()) {
setProviders(providerConfigs);
}
// 己存在<dubbo:protocol />配置, 则找出默认的<dubbo:provider />配置
} else {
ProviderConfig providerConfig = null;
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (providerConfig != null) {
throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
}
providerConfig = config;
}
}
if (providerConfig != null) {
setProvider(providerConfig);
}
}
}
}
在这里补充一下什么是默认的
2. 获取application配置
这个相对比较容易, 只是说明几点, 用户可以通过
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 (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
}
applicationConfig = config;
}
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}
3. 获取Module, 同上
4. 获取Registries, 同上
5. 获取Monitor, 同上
6. 获取Protocols, 同上
7. 获取path(服务路径)
if (StringUtils.isEmpty(getPath())) {
if (StringUtils.isNotEmpty(beanName)
&& StringUtils.isNotEmpty(getInterface())
&& beanName.startsWith(getInterface())) {
setPath(beanName);
}
}
上面代码说明如果
8. 判断该服务是否延迟发布
// <dubbo:service />上会有一个delay的配置说明
if (!supportedApplicationListener) {
// 服务暴露的方法
export();
}
delay -> 延迟注册服务时间(毫秒), 设为-1时, 表示延迟到Spring容器初始化完成时暴露服务. 而这个supportedApplicationListener属性在ServiceBean实现ApplicationContextAware接口的setApplicationContext方法中设置为true的.
根据这个源码可知, 通常我们的dubbo服务的配置:
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!isExported() && !isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
至此, 这个初始化的方法就分析完了, 下文将开始分析 处理服务暴露的方法 export() 方法.