Dubbo服务注册原理

文章目录

  • 1注册步骤
  • 2 猜想:
  • 3源码分析
    • 3.1 @DubboComponentScan
      • 3.1.1 图片总结
    • 3.2 DubboBootstrapApplicationListener.java

1注册步骤

  1. 使用注解@DubboService或@Service
  2. 扫描注解@DubboComponentScan

2 猜想:

(1)扫描注解
(2)组装url
(3)启动服务(根据url中配置的协议、端口去发布对应的服务)
(4)注册到注册中心

3源码分析

3.1 @DubboComponentScan

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({DubboComponentScanRegistrar.class})
public @interface DubboComponentScan {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

DubboComponentScanRegistrar:动态注册bean到IOC中,但是是注册哪个bean?需要分析下源码

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//获取@DubboComponentScan注解中配置的包路径
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
//注册bean到IOC容器中
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

        // @since 2.7.6 Register the common beans
        registerCommonBeans(registry);
    }

点击 registerServiceAnnotationBeanPostProcessor(packagesToScan, registry),可以看到将ServiceAnnotationBeanPostProcessor加载到IOC容器中

 private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
        builder.addConstructorArgValue(packagesToScan);
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);

    }

来看下 ServiceAnnotationBeanPostProcessor.java

  public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
        super(packagesToScan);
    }

点击父类ServiceClassPostProcessor.java的构造器,在bean加载到IOC之后会触发postProcessBeanDefinitionRegistry方法

@Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        // @since 2.7.5
        //注册基础bean
        registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);

        Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
          //如果扫描的包路径不为空,注册服务bean:serviceBean
        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            registerServiceBeans(resolvedPackagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
            }
        }

    }

registerInfrastructureBean()方法中将DubboBootstrapApplicationListener注册到容器中,
DubboBootstrapApplicationListener中的onApplicationContextEvent()方法会在spring 容器的上下文装载完成之后,触发监听

 @Override
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }

再来看下registerServiceBeans(resolvedPackagesToScan, registry) 代码
扫描所有加了@DubboService或@Service注解的bean,但不是注册到IOC容器里

 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
       serviceAnnotationTypes.forEach(annotationType -> {
           scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
       });

       for (String packageToScan : packagesToScan) {

           // Registers @Service Bean first
           scanner.scan(packageToScan);

           // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
           Set<BeanDefinitionHolder> beanDefinitionHolders =
                   findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

           if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

               for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                   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 + "]");
               }

           }

       }

   }

点击 registerServiceBean(beanDefinitionHolder, registry, scanner);

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                    DubboClassPathBeanDefinitionScanner scanner) {

       Class<?> beanClass = resolveClass(beanDefinitionHolder);

       Annotation service = findServiceAnnotation(beanClass);

       /**
        * The {@link AnnotationAttributes} of @Service annotation
        */
       AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);

       Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);

       String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

       AbstractBeanDefinition serviceBeanDefinition =
               buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

       // ServiceBean Bean name
       String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

       if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
           registry.registerBeanDefinition(beanName, serviceBeanDefinition);

           if (logger.isInfoEnabled()) {
               logger.info("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?");
           }

       }

   }

buildServiceBeanDefinition

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

       BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
       //省略代码

最终将org.apache.dubbo.config.spring.ServiceBean注册到IOC容器中

3.1.1 图片总结

在这里插入图片描述

3.2 DubboBootstrapApplicationListener.java

DubboBootstrapApplicationListener.java实现了监听接口,最终会调用ServiceConfig#export()方法,调用过程如下图:
在这里插入图片描述

 http://www.exyb.cn/news/show-333.html

原文地址:https://www.cnblogs.com/cndeveloper/p/14745432.html