服务注册流程分析01

简介: 在填充该 ServiceBean 的时候会将对应的那个声明了注解的 bean 设置到 ServiceBean 中。剩下的流程放置到下一篇文章中

在第一篇文章中、我们可以看到

@DubboService(version = "1.0.0")
public class DefaultDemoService implements DemoService {
    /**
     * The default value of ${dubbo.application.name} is ${spring.application.name}
     */
    @Value("${dubbo.application.name}")
    private String serviceName;
    public String sayHello(String name) {
        return String.format("[%s] : Hello, %s", serviceName, name);
    }
}
复制代码
@EnableDubbo
@SpringBootApplication
public class DubboProviderDemo {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(DubboProviderDemo.class, args);
        System.out.println();
    }
}
复制代码


只要使用 DubboReferenc 注解就可以将该接口暴露到服务注册中心上面

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
..............
.......
复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
复制代码


我们看一下 DubboComponentScanRegistrar

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
        // @since 2.7.6 Register the common beans
        registerCommonBeans(registry);
    }
复制代码


registerServiceAnnotationBeanPostProcessor 注册一个 BeanPostProcessor

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);
}
复制代码


registerCommonBeans 注册一些其他需要用的 Bean。其中 ReferenceAnnotationBeanPostProcessor 就是服务消费方的关键 bean

static void registerCommonBeans(BeanDefinitionRegistry registry) {
    // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
    registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
            ReferenceAnnotationBeanPostProcessor.class);
    // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093
    registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
            DubboConfigAliasPostProcessor.class);
    // Since 2.7.5 Register DubboLifecycleComponentApplicationListener as an infrastructure Bean
    registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
            DubboLifecycleComponentApplicationListener.class);
    // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean
    registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
            DubboBootstrapApplicationListener.class);
    // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
    registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
            DubboConfigDefaultPropertyValueBeanPostProcessor.class);
}
复制代码


那么对于服务提供者、ServiceAnnotationBeanPostProcessor 就是服务注册的入口了。

xml 配置文件请看 DubboNamespaceHandler


这个类看起来啥屁事都没做

public class ServiceAnnotationBeanPostProcessor extends ServiceClassPostProcessor {
    public ServiceAnnotationBeanPostProcessor(String... packagesToScan) {
        this(Arrays.asList(packagesToScan));
    }
    public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
        this(new LinkedHashSet<>(packagesToScan));
    }
    public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
        super(packagesToScan);
    }
}
复制代码


直接去它的父类 ServiceClassPostProcessor

public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
        ResourceLoaderAware, BeanClassLoaderAware {
复制代码


发现其继承了不少接口、其中 BeanDefinitionRegistryPostProcessor 为 Spring 注册完 Spring BeanDefinition 之后的回调接口

直接看它实现的方法

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    // @since 2.7.5
    registerBeans(registry, DubboBootstrapApplicationListener.class);
    Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
    if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
        registerServiceBeans(resolvedPackagesToScan, registry);
    }
    }
}
复制代码
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);
            }
        } 
      ..........
    }
复制代码

   registerBeans(registry, DubboBootstrapApplicationListener.class);

这里会注册一个 Spring 事件监听、对于后续注册服务到注册中心起着触发的作用


上面代码的大意就是扫描路径下、在类上有下面三个注解的类

private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
  DubboService.class,
  Service.class,
  com.alibaba.dubbo.config.annotation.Service.class
);
复制代码


registerServiceBean 关键点在这里

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                 DubboClassPathBeanDefinitionScanner scanner) {
    Class<?> beanClass = resolveClass(beanDefinitionHolder);
    Annotation service = findServiceAnnotation(beanClass);
    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
     // 注册到 Spring   
       registry.registerBeanDefinition(beanName, serviceBeanDefinition);
    } 
}
复制代码
private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,
                                                          AnnotationAttributes serviceAnnotationAttributes,
                                                          Class<?> interfaceClass,
                                                          String annotatedServiceBeanName) {
    BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
    MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
    String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
            "interface", "interfaceName", "parameters");
    propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));
    // References "ref" property to annotated-@Service Bean
    addPropertyReference(builder, "ref", annotatedServiceBeanName);
    // Set interface
    builder.addPropertyValue("interface", interfaceClass.getName());
    // Convert parameters into map
    builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));
    // Add methods parameters
    List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
    if (!methodConfigs.isEmpty()) {
        builder.addPropertyValue("methods", methodConfigs);
    }
  ...........
}
复制代码

网络异常,图片无法展示
|


ServiceBean 这个 bean 就是 Dubbo 服务提供者的关键。

我们为每个声明了 Dubbo 注解的 bean 再额外注册了一个 ServiceBean 、并且会将这个 bean 赋值到 ServiceBean 的 ref 变量中

addPropertyReference(builder, "ref", annotatedServiceBeanName);         
复制代码


BeanDefinitionValueResolver

public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
   // We must check each value to see whether it requires a runtime reference
   // to another bean to be resolved.
   if (value instanceof RuntimeBeanReference) {
      RuntimeBeanReference ref = (RuntimeBeanReference) value;
      return resolveReference(argName, ref);
   }
复制代码
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
   try {
      Object bean;
      Class<?> beanType = ref.getBeanType();
      ........
      else {
         String resolvedName;
        ........
         else {
            resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
            bean = this.beanFactory.getBean(resolvedName);
         }
         this.beanFactory.registerDependentBean(resolvedName, this.beanName);
      }
      if (bean instanceof NullBean) {
         bean = null;
      }
      return bean;
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            this.beanDefinition.getResourceDescription(), this.beanName,
            "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
   }
}
复制代码


在填充该 ServiceBean 的时候会将对应的那个声明了注解的 bean 设置到 ServiceBean 中。


剩下的流程放置到下一篇文章中



目录
相关文章
|
21天前
|
数据安全/隐私保护 开发者
注册实现流程
注册实现流程
11 0
|
2月前
|
存储
注册中心是如何工作的
【2月更文挑战第8天】
|
9月前
|
弹性计算 数据安全/隐私保护
阿里云注册流程详解
很多小白用户不知道怎么注册阿里云,下面小编就和大家系统讲解一下
|
Dubbo Java 应用服务中间件
服务注册流程分析02
上一篇文章中、我们已经知道 Dubbo 会额外注册 ServiceBean 到 Spring 容器中、因为需要借助这个 ServiceBean 注册到服务中心
127 0
|
Java 数据库 开发者
用户模块之注册功能流程分析|学习笔记
快速学习 用户模块之注册功能流程分析
122 0
|
数据安全/隐私保护
阿里云注册流程
阿里云注册流程快速版,简洁注册流程
328 0
阿里云注册流程
|
Java 数据库 开发者
注册功能流程分析 | 学习笔记
快速学习注册功能流程分析
140 0
注册功能流程分析 | 学习笔记
|
数据处理
项目前期准备--了解项目的数据处理流程及注册功能(2)
项目前期准备--了解项目的数据处理流程及注册功能(2)
147 0
|
SQL XML Java
项目前期准备--了解项目的数据处理流程及注册功能(1)
项目前期准备--了解项目的数据处理流程及注册功能(1)
126 0
|
数据处理
freeModbus流程分析
freeModbus流程注解
1084 0
freeModbus流程分析

热门文章

最新文章