Dubbo2.7详解( 二 )

5)registrar.registerBeanDefinitions方法的调用情况
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {private final Log log = LogFactory.getLog(getClass());private ConfigurableEnvironment environment;@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//执行DubboConfigBindingRegistrarAnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName()));registerBeanDefinitions(attributes, registry);}protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) {// prefix = "dubbo.application"String prefix = environment.resolvePlaceholders(attributes.getString("prefix"));// type = ApplicationConfig.classClass<? extends AbstractConfig> configClass = attributes.getClass("type");boolean multiple = attributes.getBoolean("multiple");//针对配置分别进行注册成Bean对象,方法1registerDubboConfigBeans(prefix, configClass, multiple, registry);}//方法1,因为Single和Multiple都是走同一套逻辑,采用参数boolean multiple区分private void registerDubboConfigBeans(String prefix, Class<? extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry) {// 从properties文件中根据前缀拿对应的配置项,比如根据dubbo.application前缀,// 就可以拿到如下配置:// dubbo.application.name=dubbo-demo-provider-application// dubbo.application.logger=log4jMap<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix);// 如果没有相关的配置项,则不需要注册BeanDefinitionif (CollectionUtils.isEmpty(properties)) {if (log.isDebugEnabled()) {log.debug(...);}return;}// 根据配置项生成beanNames,为什么会有多个?// 普通情况一个dubbo.application前缀对应一个ApplicationConfig类型的Bean// 特殊情况下(配置两种协议),比如dubbo.protocols对应了://dubbo.protocols.p1.name=dubbo//dubbo.protocols.p1.port=20880//dubbo.protocols.p1.host=0.0.0.0//dubbo.protocols.p2.name=http//dubbo.protocols.p2.port=8082//dubbo.protocols.p2.host=0.0.0.0// 那么就需要对应两个ProtocolConfig类型的Bean , 那么就需要两个beanName:p1和p2// 这里就是multiple为true或false的区别,名字的区别,根据multiple用来判断是否从配置项中获取beanName// 如果multiple为false,则看有没有配置id属性 , 如果没有配置则自动生成一个beanName.Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : Collections.singleton(resolveSingleBeanName(properties, configClass, registry));for (String beanName : beanNames) {// 为每个beanName,注册一个空的BeanDefinition,方法2registerDubboConfigBean(beanName, configClass, registry);// 为每个bean注册一个DubboConfigBindingBeanPostProcessor的Bean后置处理器,方法3//这里存在的问题就是对应每一种配置都会产生对应的BeanPostProcessor,最多好像也就是10种左右//但其实一个就可以做的任务,拓展成多个貌似不太合理,结合处理逻辑都是同一套就很尴尬registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry);}// 注册一个NamePropertyDefaultValueDubboConfigBeanCustomizer的beanregisterDubboConfigBeanCustomizers(registry);}//方法2,为对应的配置生成一个beanDefinition,并注入到容器private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,BeanDefinitionRegistry registry) {BeanDefinitionBuilder builder = rootBeanDefinition(configClass);AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();registry.registerBeanDefinition(beanName, beanDefinition);// ApplicatinoConfig对象if (log.isInfoEnabled()) {log.info("...); //日志记录}}//方法3private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple,BeanDefinitionRegistry registry) {// 注册一个DubboConfigBindingBeanPostProcessor的Bean// 每个XxConfig的Bean对应一个DubboConfigBindingBeanPostProcessor的Bean// 比如 , 一个ApplicationConfig对应一个DubboConfigBindingBeanPostProcessor,// 一个ProtocolConfig也会对应一个DubboConfigBindingBeanPostProcessor// 在构造DubboConfigBindingBeanPostProcessor的时候会指定构造方法的值,这样就可以区别开来了Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class;BeanDefinitionBuilder builder = rootBeanDefinition(processorClass);// 真实的前缀 , 比如dubbo.registries.r2String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix;// 添加两个构造方法参数值 , 所以会调用DubboConfigBindingBeanPostProcessor的两个参数的构造方法builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registerWithGeneratedName(beanDefinition, registry);if (log.isInfoEnabled()) {log.info(...);}}private void registerDubboConfigBeanCustomizers(BeanDefinitionRegistry registry) {registerInfrastructureBean(registry, BEAN_NAME, NamePropertyDefaultValueDubboConfigBeanCustomizer.class);}@Overridepublic void setEnvironment(Environment environment) {Assert.isInstanceOf(ConfigurableEnvironment.class, environment);this.environment = (ConfigurableEnvironment) environment;}private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) {Set<String> beanNames = new LinkedHashSet<String>();// 比如dubbo.protocols.p1.name=dubbo的propertyName为p1.namefor (String propertyName : properties.keySet()) {// propertyName为p1.nameint index = propertyName.indexOf(".");if (index > 0) {// 截取beanName名字为p1String beanName = propertyName.substring(0, index);beanNames.add(beanName);}}return beanNames;}private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,BeanDefinitionRegistry registry) {// 配置了dubbo.application.id=appl,那么appl就是beanNameString beanName = (String) properties.get("id");// 如果beanName为null,则会进入if分支,由spring自动生成一个beanName,比如org.apache.dubbo.config.ApplicationConfig#0if (!StringUtils.hasText(beanName)) {BeanDefinitionBuilder builder = rootBeanDefinition(configClass);beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);}return beanName;}}

推荐阅读