SpringBoot与Dubbo整合源码分析


Demo

SpringBoot整合Dubbo只需加个依赖,服务提供者加注解@Service (dubbo的不是spring的,后改为@DubboService),服务消费者加注解@Reference注解

加依赖

<!-- Dubbo集成进SpringBoot -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.5</version>
</dependency>

<!-- zookeeper所需依赖 -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-dependencies-zookeeper</artifactId>
    <version>2.7.8</version>
    <type>pom</type>
    <exclusions>
        <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

服务提供者

@Service(group = "default", version = "1.0")
@Slf4j
public class DemoServiceImpl implements DemoService {
    @Override
    public String called(String name) {
        URL url = RpcContext.getContext().getUrl();
        String msg = url.getProtocol() + ":" + url.getPort() + ",Hello," + name;
        log.info(msg);
        return msg;
    }
}

服务消费者

@RestController
@Slf4j
public class DemoServiceController {

    @Reference(group = "default", version = "1.0", cache = "lru")
    private DemoService demoService;

    @RequestMapping("/default")
    public String test() {
        return demoService.called("默认服务");
    }
}

入口

任何框架与SpringBoot集成都是通过starter包和autoconfigure进行集成,我们首先看到jar包依赖这边我们依赖了dubbo-spring-boot-starter。

我们看到这2个autoconfigure下的spring.factories

这里我们重点关注DubboAutoConfiguration这个类

DubboAutoConfiguration

这个类的重点是@EnableDubboConfigServiceClassPostProcessor

功能:

  1. @EnableDubboConfig去解析配置类
  2. ServiceClassPostProcessor后置处理器通过springboot自动装配注入到spring中

这里我们一步一步的来看

@EnableDubboConfig

打开这个类我们发现@Import(DubboConfigConfigurationRegistrar.class),DubboConfigConfigurationRegistrar这个类重写了ImportBeanDefinitionRegistrar(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法,这个方法包含参数BeanDefinitionRegistry,Dubbo可以通过BeanDefinitionRegistry注册BeanDefinition。(Spring Import相关知识)

DubboConfigConfigurationRegistrar

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 获取EnableDubboConfig上面的信息,这里主要获取的是multiple的值默认为true
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        // 获取EnableDubboConfig标签中的multiple属性默认为true
        boolean multiple = attributes.getBoolean("multiple");

        // 注册bean定义 ===== 重点 ===========
        registerBeans(registry, DubboConfigConfiguration.Single.class);

        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }

        // Since 2.7.6
        // 注册公共的bean,5个
        // ReferenceAnnotationBeanPostProcessor,DubboConfigAliasPostProcessor,
        // DubboLifecycleComponentApplicationListener,DubboBootstrapApplicationListener,
        // DubboConfigDefaultPropertyValueBeanPostProcessor
        registerCommonBeans(registry);
    }
}

需要注意的是这里注册了ReferenceAnnotationBeanPostProcessor,这个Bean后置处理器和解析@Reference相关

public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {

    Set<Class<?>> classesToRegister = new LinkedHashSet<Class<?>>(asList(annotatedClasses));
    Iterator<Class<?>> iterator = classesToRegister.iterator();
     // 已经被注册过得Bean不在重新注册,移除classesToRegister中已注册过的bean
    while (iterator.hasNext()) {
        Class<?> annotatedClass = iterator.next();
        if (isPresentBean(registry, annotatedClass)) {
            iterator.remove();
        }
    }

    // 通过AnnotatedBeanDefinitionReader批量注册classesToRegister
    AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
    reader.register(classesToRegister.toArray(EMPTY_CLASS_ARRAY));
}

DubboConfigConfiguration

public class DubboConfigConfiguration {
    // 通过前缀(prefix)去spring的environment中匹配,并通过后置处理器将值绑定到类(type)中,生成beanDefinition
    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.module", type = ModuleConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metrics", type = MetricsConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.ssl", type = SslConfig.class)
    })
    public static class Single {
       }
    
    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
    })
    public static class Multiple {
    }
}

观察这个类中包含了Multiple和Single2个子类,而这2个子类上都有@EnableConfigurationBeanBindings注解。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigurationBeanBindingsRegister.class)
public @interface EnableConfigurationBeanBindings {
    EnableConfigurationBeanBinding[] value();
}

注解上同样import了一个类ConfigurationBeanBindingsRegister,发现这个类实现了ImportBeanDefinitionRegistrar, EnvironmentAware2个类,知道spring的都知道ImportBeanDefinitionRegistrar表明了可以注册beanDefinition,EnvironmentAware表明可以设置环境。

public class ConfigurationBeanBindingsRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private ConfigurableEnvironment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 获取@EnableConfigurationBeanBindings注解上的所有属性值
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableConfigurationBeanBindings.class.getName()));
        // 拿到多个@EnableDubboConfigBinding注解
        AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");

        ConfigurationBeanBindingRegistrar registrar = new ConfigurationBeanBindingRegistrar();
        registrar.setEnvironment(environment);

        for (AnnotationAttributes element : annotationAttributes) {
            // 逐个解析@EnableDubboConfigBinding注解 ======这个方法可以看下============
            registrar.registerConfigurationBeanDefinitions(element, registry);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        this.environment = (ConfigurableEnvironment) environment;
    }
}

ConfigurationBeanBindingRegistrar#registerConfigurationBeanDefinitions

  1. DubboConfigConfiguration下的@EnableDubboConfigBinding注解
  2. 通过@EnableDubboConfigBinding注解中的前缀匹配到配置文件中的配置项
  3. 通过@EnableDubboConfigBinding中class和配置项生成bean定义
  4. 注册bean定义
// @EnableDubboConfigBinding注解上的所有值
public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {
    String prefix = getRequiredAttribute(attributes, "prefix");
    prefix = environment.resolvePlaceholders(prefix);
    Class<?> configClass = getRequiredAttribute(attributes, "type");
    boolean multiple = getAttribute(attributes, "multiple", valueOf(DEFAULT_MULTIPLE));
    boolean ignoreUnknownFields = getAttribute(attributes, "ignoreUnknownFields", valueOf(DEFAULT_IGNORE_UNKNOWN_FIELDS));
    boolean ignoreInvalidFields = getAttribute(attributes, "ignoreInvalidFields", valueOf(DEFAULT_IGNORE_INVALID_FIELDS));
    // ===================重要方法===================
    registerConfigurationBeans(prefix, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, registry);
}


private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple,
                                        boolean ignoreUnknownFields, boolean ignoreInvalidFields,
                                        BeanDefinitionRegistry registry) {
    // 从配置文件中根据前缀拿对应的配置项
    Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(environment.getPropertySources(), environment, prefix);
    
    // multiple控制是否会存在有多个bean,比如
    /*dubbo.protocols.p1.id=dubbo1
    dubbo.protocols.p1.name=dubbo
    dubbo.protocols.p1.port=20881
    dubbo.protocols.p1.host=0.0.0.0
        
    dubbo.protocols.p2.id=dubbo1
    dubbo.protocols.p2.name=dubbo
    dubbo.protocols.p2.port=20881
    dubbo.protocols.p2.host=0.0.0.0*/
    // 这种讲道理应该生成多个bean,而且这多个bean直接按protocols后的p1,p2命名
    Set<String> beanNames = multiple ? resolveMultipleBeanNames(configurationProperties) :
            singleton(resolveSingleBeanName(configurationProperties, configClass, registry));

    // 注册上面解析出来的beanName为beanDefinition,,但需要注意的是这里只是beanDeinition,其中的属性值并没有设置,是在bean的后置处理器中处理
    // 在注册过程中beanDefinition.setSource(ENABLE_CONFIGURATION_BINDING_CLASS);后面会bean后置处理器会通过它区分bean是否是这里引过去的
    for (String beanName : beanNames) {
        registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields,
                configurationProperties, registry);
    }

    // 注册一个ConfigurationBeanBindingPostProcessor的Bean后置处理器
    registerConfigurationBindingBeanPostProcessor(registry);
}

ConfigurationBeanBindingPostProcessor

主要解决的是之前只是注册了beanDefinition,属性值并没有设到bean中,我们需要在bean实例化之前进行属性赋值,所以需要在bean的后置处理器中进行处理。

我们发现ConfigurationBeanBindingPostProcessor实现了BeanPostProcessor,并且实现了postProcessBeforeInitialization接口,从这里可以看出实例化之前调用postProcessBeforeInitialization接口进行属性赋值。

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 获取beanDefinition
    BeanDefinition beanDefinition = getNullableBeanDefinition(beanName);
    // 判断bean是不是@EnableConfigurationBeanBinding注册的bean
    if (isConfigurationBean(bean, beanDefinition)) {
        // 属性值绑定到bean上
        bindConfigurationBean(bean, beanDefinition);
        customize(beanName, bean);
    }

    return bean;
}

ServiceClassPostProcessor

这个类主要干的事就是扫描包,注册beanDefinition,由于它实现了BeanDefinitionRegistryPostProcessor,是一个bean工厂的后置处理器(可以注册bean定义)

有个注意点,Dubbo扫描包注册成的beanDefinition不是一个是2个,一个是Spring的BeanDefinition还有一个是Dubbo的ServiceBean,为什么还需要一个Dubbo的ServiceBean,因为Dubbo如果仅仅只使用Spring的BeanDefinition会缺少很多@Service的注解信息,Dubbo会利用@Service上的信息进行填充产生一个新的bean-ServiceBean。而且用自己的bean可以做很多的处理

所以在扫描到⼀个@Service注解后,其实会得到两个Bean:

  1. 服务实现类本身Bean对象
  2. 对应的ServiceBean类型的Bean对象
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    // @since 2.7.5
    // 注册一个事件监听器,spring事件为ContextRefreshedEvent时,会调用dubboBootstrap.start();
    registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);

    // 获取包扫描路径
    Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);

    if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
        // 扫描包,注册ServiceBean ========重点===========
        registerServiceBeans(resolvedPackagesToScan, registry);
    } else {
        if (logger.isWarnEnabled()) {
            logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }
    }
}

ServiceAnnotationBeanPostProcessor#registerServiceBeans

  1. 扫描被标注了@DubboService和@Service注解的类
  2. 注册bean
// ====================去掉了一些不必要的log代码===========
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

    DubboClassPathBeanDefinitionScanner scanner =
            new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

    scanner.setBeanNameGenerator(beanNameGenerator);

    // refactor @since 2.7.7
    // 扫描一些有注解的类,这注解主要有3种(不同版本不一样,需注意)
    // DubboService.class,(新版本,与Spring区分)
    // org.apache.dubbo.config.annotation.Service,(老版本)
    // com.alibaba.dubbo.config.annotation.Service.class(兼容)
    serviceAnnotationTypes.forEach(annotationType -> {
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
    });

    for (String packageToScan : packagesToScan) {

        // Registers @Service Bean first
        // 调用Spring的scan方法会生成beanDefinition最后生成了bean,这就是服务实现类本身Bean对象
        scanner.scan(packageToScan);

        // 查找被@Service注解的类的BeanDefinition(无论这个类有没有被@ComponentScan注解标注了)
        Set<BeanDefinitionHolder> beanDefinitionHolders =
                findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
           // 扫描到BeanDefinition开始处理它
            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                // ============================核心方法=====================
                registerServiceBean(beanDefinitionHolder, registry, scanner);
            }
        } 
    }
}

ServiceAnnotationBeanPostProcessor#registerServiceBean

注册Bean

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                 DubboClassPathBeanDefinitionScanner scanner) {
    // 服务实现类
    Class<?> beanClass = resolveClass(beanDefinitionHolder);
    // 拿到注解,这里拿到的是@Service
    Annotation service = findServiceAnnotation(beanClass);
    // 获取注解上的属性值(这里也包括了缺省值)
    AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
    // 服务实现类的接口类
    Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
    // 服务实现类对应的bean的名字
    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
    // 构建ServiceBeanDefinition  这个过程可以看下==========================稍重点====================
    AbstractBeanDefinition serviceBeanDefinition =
            buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

    // ServiceBean的名字
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

    // 检查重复的候选bean
    if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        // ServiceBean注册为beanDefinition
        registry.registerBeanDefinition(beanName, serviceBeanDefinition);
    } 
}

buildServiceBeanDefinition

生成一个ServiceBean对应的BeanDefinition

private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,
                                                          AnnotationAttributes serviceAnnotationAttributes,
                                                          Class<?> interfaceClass,
                                                          String annotatedServiceBeanName) {

    BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

    MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
    // 把serviceAnnotation中的参数值赋值给ServiceBean的属性
    // 忽略掉一些属性,因为这些属性不能做简单的属性赋值,需要经过一些操作,
    // 比如protocol这个是需要引用的是bean,而不是字符串,这里我们就要通过字符串去找到bean赋值
    String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
            "interface", "interfaceName", "parameters");

    propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));

    // ref属性赋值为另外一个bean, 对应的就是被@Service注解的服务实现类对应的bean
    addPropertyReference(builder, "ref", annotatedServiceBeanName);
    // 赋值接口
    builder.addPropertyValue("interface", interfaceClass.getName());
    // 赋值参数
    builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));
    // Add methods parameters
    List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
    if (!methodConfigs.isEmpty()) {
        builder.addPropertyValue("methods", methodConfigs);
    }
    // 下面也是一些参数的赋值,就删掉了。。。。。。
    
    // beanDefinition返回
    return builder.getBeanDefinition();

}

generateServiceBeanName

生成ServiceBean的bean名称

逻辑很简单就是把group,version等拼接

private String generateServiceBeanName(AnnotationAttributes serviceAnnotationAttributes, Class<?> interfaceClass) {
    ServiceBeanNameBuilder builder = create(interfaceClass, environment)
            .group(serviceAnnotationAttributes.getString("group"))
            .version(serviceAnnotationAttributes.getString("version"));
    return builder.build();
}

ReferenceAnnotationBeanPostProcessor

这个后置处理器主要是针对于@Reference生成ReferenceBean并进行依赖注入

在@EnableDubboConfig下的DubboConfigConfigurationRegistrar类中registerCommonBeans方法注入了ReferenceAnnotationBeanPostProcessor后置处理器我们发现这个后置处理器实现了InstantiationAwareBeanPostProcessor.postProcessPropertyValues这个方法,而这个方法是在依赖注入的时候调用的。

// 构造方法中传入三个匹配注解,存到annotationTypes,后面匹配的时候会使用存到annotationTypes
public ReferenceAnnotationBeanPostProcessor() {
    super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
}


@Override
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    // 寻找需要注入的属性被@Reference注解
    // 这里通过构造方法配置的DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class中找到注解的方法或字段
    // AnnotatedFieldElement  AnnotatedMethodElement
    InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    } catch (BeanCreationException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
                + " dependencies is failed", ex);
    }
    return pvs;
}

buildAnnotatedMetadata

private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
    Collection<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
    Collection<AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
    return new AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
}

doGetInjectedBean

注入调用栈

metadata.inject->element.inject->AnnotatedFieldElement#inject->getInjectedObject->doGetInjectedBean

@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {
    /**
     * The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
     */
    // 生成referencedBeanName, 规则ServiceBean:interfaceClassName:version:group
    // 是本地的ServiceBean(当前应用自己提供的ServiceBean)
    // 例: ServiceBean:com.dm.DemoService:1.0:default
    String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

    /**
     * The name of bean that is declared by {@link Reference @Reference} annotation injection
     */
    // 根据@Reference注解的信息生成referenceBeanName
    // 这里是把它作为key值,为了区分相同注入相同实现类却不是相同属性的类比如
    /*
    @Reference(group=default)
    private DemoService demoService1;
    @Reference(group=hhh)
    private DemoService demoService2;
    */
    // 例:@Reference(group=default,cache=lru,version=1.0) com.dm.DemoService
    String referenceBeanName = getReferenceBeanName(attributes, injectedType);

    // 生成一个ReferenceBean对象(这里是会判断缓存中是不是有,有就会使用之前的类)
    ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

    // 判断spring容器中是否有这个serviceBean
    boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

    prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);

    // 注册referenceBean到Spring容器
    // 这里面会首先判断spring是不是有这个ServiceBean,有的话直接注册一个referencedBeanName的别名,没有的话就以referencedBeanName为beanName注册一个beanDefinition
    registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

    cacheInjectedReferenceBean(referenceBean, injectedElement);

    // 获取一个代理对象
    return referenceBean.get();
}

总结

这里的总结分为三部分

  • 配置文件的解析与生成多个配置bean(ApplicationConfig, ModuleConfig,RegistryConfig.class,ProtocolConfig)

    1. 通过DubboConfigConfiguration#Single或Multiple配置的前缀和配置类
    2. 通过前缀和配置类去spring的environment进行匹配,然后将匹配获取的值存入配置类的BeanDefinition中
    3. 通过bean后置处理器在Bean实例化之前进行属性绑定
    4. 完整bean生成
  • 扫描@Service并生成ServiceBean

    1. 通过bean工厂的后置处理器扫描有@Service,@DubboService标注的类
    2. 扫描后会生成一个当前实现类的beanDefinition(spring生成的)
    3. 然后生成一个Dubbo的beanDefinition实现ServiceBean,目的为了可以处理跟多Dubbo逻辑,还有存储@Service注解上的属性值
  • 注入属性@Reference

    1. 在Bean的后置处理器中调用postProcessPropertyValues方法处理
    2. 首先扫描注入点也就是被@Reference,@DubboReference注解的方法和类
    3. 根据@Reference中的注解信息(group,version)生成一个新的baneName为referencedBeanName,
    4. 根据@Reference中的注解信息(group,version)生成一个新的baneName为缓存key值为referenceBeanName,
    5. 判断容器中是不是有referencedBeanName(有,是因为当前注入的类是本项目@DubboService标注的类);有注册一个referencedBeanName的别名,没有的话就以referencedBeanName为beanName注册一个beanDefinition
    6. 然后创建一个代理对象进行依赖注入(这里为什么要创建代理对象呢?直接使用beanDefinition生成bean不行吗?简单来说就是和ServiceBean创建代理对象一个道理,它会有一些Dubbo逻辑处理在其中,还会依赖存储一些属性值)

文章作者: dm
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 dm !
评论
 上一篇
Dubbo服务引用 Dubbo服务引用
前言在SpringBoot与Dubbo整合源码分析那一篇博文中有说到在Spring启动过程中会对@DubboReference标注的对象进行赋值,赋值的内容就是ReferenceBean#get方法返回的代理对象。而这代理对象的生成便是服务
2023-06-10
下一篇 
Dubbo SPI机制 Dubbo SPI机制
什么是 SPISPI全称是Service provider interface,顾名思义就是服务提供接口,本质上就是以接口的形式提供服务。 SPI目标就是对应用提供可拔插的服务,应用会首先提供一个接口进行扩展。我们只需要在META-INF下
2023-05-17
  目录