一、前言
SpringBoot启动时,dubbo初始化相关的类;
1、OverrideDubboConfigApplicationListener;
2、ServerBean;
3、DubboConfigBindingRegistrar;
4、ServiceAnnotationBeanPostProcessor;
5、AbstractConfig
二、类起到的作用
1、OverrideDubboConfigApplicationListener
@Order // LOWEST_PRECEDENCE Make sure last execution
public class OverrideDubboConfigApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
/**
* Gets Logger After LoggingSystem configuration ready
* @see LoggingApplicationListener
*/
final Logger logger = LoggerFactory.getLogger(getClass());
ConfigurableEnvironment environment = event.getEnvironment(); //加载yml文件
boolean override = environment.getProperty(OVERRIDE_CONFIG_PROPERTY_NAME, boolean.class,
DEFAULT_OVERRIDE_CONFIG_PROPERTY_VALUE);
if (override) {
//遍历yml文件,把dubbo的属性,以键值对的形式存放
SortedMap<String, Object> dubboProperties = filterDubboProperties(environment);
//保存到本地的ConcurrentHashMap中
ConfigUtils.getProperties().putAll(dubboProperties);
if (logger.isInfoEnabled()) {
logger.info("Dubbo Config was overridden by externalized configuration {}", dubboProperties);
}
} else {
if (logger.isInfoEnabled()) {
logger.info("Disable override Dubbo Config caused by property {} = {}", OVERRIDE_CONFIG_PROPERTY_NAME, override);
}
duboo的配置应用程序,onApplicationEvent()主要做的是将yml或者其他配置文件解析,封装到Map集合中,方便后续的调用;
2、ServerBean
public void afterPropertiesSet() throws Exception {
// 判断是否解析过 provider 配置,解析过则不再解析
if (getProvider() == null) {
// 获取所有 ProviderConfig 类型的 bean
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
if (providerConfigMap != null && providerConfigMap.size() > 0) {
// 获取所有 ProtocolConfig 类型的 bean
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()) {
// 添加默认的 ProviderConfig
providerConfigs.add(config);
}
}
if (!providerConfigs.isEmpty()) {
// 将 ProviderConfig 转换为 ProtocolConfig 赋值给 protocols 成员属性
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) {
// 设置 provider 配置
setProvider(providerConfig);
}
}
}
}
//获取yml中dubbo application name的属性
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);
}
}
}
//获取yml中dubbo module的属性
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);
}
}
}
//获取yml中dubbo registries的属性
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
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.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
}
//获取yml中dubbo monitor的属性
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);
}
}
}
//获取yml中dubbo protocols的属性
if ((getProtocols() == null || getProtocols().isEmpty())
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
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.isEmpty()) {
super.setProtocols(protocolConfigs);
}
}
}
//获取path,实际是beanName,组成“接口实现类名:接口的包名:@Service的属性值”
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();
}
}
总结:此类主要用于检查ServiceBean的某个属性(这里的属性包含如下6个)是否为空,如果为空,从applicationContext获取相应类型的bean,如果获取到了, 把获取到的属性添加到dubbo提供的AbstractInterfaceConfig类中
ProviderConfig provider:有没有配置dubbo:provider ApplicationConfig
application:有没有配置dubbo:application ModuleConfig
module:有没有配置dubbo:module List registries:有没有配置dubbo:registry
MonitorConfig monitor:有没有配置dubbo:monitor List
protocols:有没有配置dubbo:protocol String path:服务名称
3、DubboConfigBindingRegistrar
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private final Log log = LogFactory.getLog(getClass());
//封装yml的属性
private ConfigurableEnvironment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName()));
registerBeanDefinitions(attributes, registry);
}
protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) {
//获取yml文件
String prefix = environment.resolvePlaceholders(attributes.getString("prefix"));
Class<? extends AbstractConfig> configClass = attributes.getClass("type");
boolean multiple = attributes.getBoolean("multiple");
registerDubboConfigBeans(prefix, configClass, multiple, registry);
}
private void registerDubboConfigBeans(String prefix,
Class<? extends AbstractConfig> configClass,
boolean multiple,
BeanDefinitionRegistry registry) {
//根据yml的key获取value,并保存在Map中
Map<String, String> properties = getSubProperties(environment.getPropertySources(), prefix);
if (CollectionUtils.isEmpty(properties)) {
if (log.isDebugEnabled()) {
log.debug("There is no property for binding to dubbo config class [" + configClass.getName()
+ "] within prefix [" + prefix + "]");
}
return;
}
Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) :
Collections.singleton(resolveSingleBeanName(properties, configClass, registry));
for (String beanName : beanNames) {
//注册能够映射beanName的config类;duboo提供了一系列跟yml配置属性对应的类
registerDubboConfigBean(beanName, configClass, registry);
registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry);
}
}
private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
//把dubbo的config类注册进容器;
registry.registerBeanDefinition(beanName, beanDefinition);
if (log.isInfoEnabled()) {
log.info("The dubbo config bean definition [name : " + beanName + ", class : " + configClass.getName() +
"] has been registered.");
}
}
private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple,
BeanDefinitionRegistry registry) {
Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class;
BeanDefinitionBuilder builder = rootBeanDefinition(processorClass);
// actualPrefix=yml中key值
String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix;
//把yml属性的值通过config类的构造方法注入
builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//把对应的beanDefinition和属性放入容器的集合中,实例化对象就是从此集合中取出
registerWithGeneratedName(beanDefinition, registry);
if (log.isInfoEnabled()) {
log.info("The BeanPostProcessor bean definition [" + processorClass.getName()
+ "] for dubbo config bean [name : " + beanName + "] has been registered.");
}
总结:根据yml配置文件的key,找到对应的dubbo的config类,并注入容器中,以构造方法的形式,把value传入到config类中;
4、ServiceAnnotationBeanPostProcessor
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//解析扫描包,主要是看包里面的类是否有跟duboo相关的注解;(此方法为整个类方法执行的起点)
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
for (String packageToScan : packagesToScan) {
if (StringUtils.hasText(packageToScan)) {
String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim());
resolvedPackagesToScan.add(resolvedPackageToScan);
}
}
return resolvedPackagesToScan;
}
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
//创建dubbo类的扫描器
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
//添加@service的过滤器,意思用于扫描被@service标识的类;
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
//查找被@service标识类的持有者
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
//注册被@service标识的类
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + "]");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
+ packageToScan + "]");
}
private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
BeanNameGenerator beanNameGenerator = null;
if (registry instanceof SingletonBeanRegistry) {
SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry);
beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
}
if (beanNameGenerator == null) {
if (logger.isInfoEnabled()) {
logger.info("BeanNameGenerator bean can't be found in BeanFactory with name ["
+ CONFIGURATION_BEAN_NAME_GENERATOR + "]");
logger.info("BeanNameGenerator will be a instance of " +
AnnotationBeanNameGenerator.class.getName() +
" , it maybe a potential problem on bean name generation.");
}
beanNameGenerator = new AnnotationBeanNameGenerator();
}
return beanNameGenerator;
private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders(
ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
BeanNameGenerator beanNameGenerator) {
Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan);
Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<BeanDefinitionHolder>(beanDefinitions.size());
for (BeanDefinition beanDefinition : beanDefinitions) {
String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
beanDefinitionHolders.add(beanDefinitionHolder);
}
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
//把@Service的属性值获取出来;
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
//此方法主要是把@Service标识的类名和@service的属性值拼接在一起;
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
//把beanname注册到容器的集合中去;
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.warn("The BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean has been registered with name : " + beanName);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean[ bean name : " + beanName +
"] was be found , Did @DubboComponentScan scan to same package in many times?");
}
private String generateServiceBeanName(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) {
StringBuilder beanNameBuilder = new StringBuilder(ServiceBean.class.getSimpleName());
beanNameBuilder.append(SEPARATOR).append(annotatedServiceBeanName);
String interfaceClassName = interfaceClass.getName();
beanNameBuilder.append(SEPARATOR).append(interfaceClassName);
String version = service.version();
if (StringUtils.hasText(version)) {
beanNameBuilder.append(SEPARATOR).append(version);
}
String group = service.group();
if (StringUtils.hasText(group)) {
beanNameBuilder.append(SEPARATOR).append(group);
}
return beanNameBuilder.toString();
}
总结:此类继承了BeanFactoryPostProcessor,作用是bean对象初始化时,调用bean的后置处理器(解析bean对象上的注解),并把相应的类注入容器中;
5、AbstractConfig
public abstract class AbstractConfig implements Serializable {
static {
legacyProperties.put("dubbo.protocol.name", "dubbo.service.protocol");
legacyProperties.put("dubbo.protocol.host", "dubbo.service.server.host");
legacyProperties.put("dubbo.protocol.port", "dubbo.service.server.port");
legacyProperties.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size");
legacyProperties.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout");
legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
legacyProperties.put("dubbo.service.url", "dubbo.service.address");
}
protected static void appendProperties(AbstractConfig config) {
if (config == null) {
return;
}
// 获取标签名称(config 名称除去 Config 或 Bean 后缀转成小写
//例如 ProviderConfig --> provider、ServiceBean --> service)
//拼接前缀,eg:ProviderConfig --> dubbo.provider
String prefix = "dubbo." + getTagName(config.getClass()) + ".";
Method[] methods = config.getClass().getMethods();
for (Method method : methods) {
try {
String name = method.getName();
if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers())
&& method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) {
// 将 setter 驼峰命名去掉 set 后转成.连接的命名,如 setDumpDirectory --> dump.directory
String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");
String value = null;
if (config.getId() != null && config.getId().length() > 0) {
// 如果 id 属性不为空,携带 id 拼接 key 尝试从系统属性中获取相关配置
String pn = prefix + config.getId() + "." + property;
value = System.getProperty(pn);
if (!StringUtils.isBlank(value)) {
logger.info("Use System Property " + pn + " to config dubbo");
}
}
if (value == null || value.length() == 0) {
// 如果 id 属性为空,不带 id 拼接 key 尝试从系统属性中获取相关配置
String pn = prefix + property;
value = System.getProperty(pn);
if (!StringUtils.isBlank(value)) {
logger.info("Use System Property " + pn + " to config dubbo");
}
}
if (value == null || value.length() == 0) {
Method getter;
try {
// 如果从系统属性中没有获取到配置,则尝试获取响应 getter 方法
getter = config.getClass().getMethod("get" + name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e) {
try {
// boolean 类型的属性的 getter 方法可能以 is 开头
getter = config.getClass().getMethod("is" + name.substring(3), new Class<?>[0]);
} catch (NoSuchMethodException e2) {
getter = null;
}
}
if (getter != null) {
if (getter.invoke(config, new Object[0]) == null) {
if (config.getId() != null && config.getId().length() > 0) {
value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);
}
if (value == null || value.length() == 0) {
value = ConfigUtils.getProperty(prefix + property);
}
if (value == null || value.length() == 0) {
String legacyKey = legacyProperties.get(prefix + property);
if (legacyKey != null && legacyKey.length() > 0) {
value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));
}
}
}
}
}
if (value != null && value.length() > 0) {
method.invoke(config, new Object[]{convertPrimitive(method.getParameterTypes()[0], value)});
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
总结:获取它的子类中成员变量名和属性,成员变量名按特定的拼接方式,拼接成与legacyProperties的key值对应,之后把成员变量属性映射到value中;
三、总结
SpringBoot启动时,OverrideDubboConfigApplicationListener会以key-value形式保存配置文件的属性,DubboConfigBindingRegistrar把dubbo提供的config类,注入容器中,并把配置文件的value以构造方法的形式注入类中,ServiceBean检查config类的属性是否为null,是否要再次设置,ServiceAnnotationBeanPostProcessor把@service注解标识的类和注解的属性注入容器,并把类名和属性拼接成beanname;