Dubbo annotation @ DubboService mechanism

The versions of this article are based on version 2.7.7. 2.7.7 provides the @ EnableDubbo annotation for integration with spring.

For the explanation of the source code of the Import annotation, I recommend reading this blog, which is very clear: https://blog.csdn.net/boling_cavalry/article/details/82530167

From the use of Dubbo in Spring, there are two important annotations, @ DubboService and @ DubboReference.
The two annotations are parsed in ServiceAnnotationBeanPostProcessor and ReferenceAnnotationBeanPostProcessor respectively. This article will trace back to Dubbo's annotation startup, and finally to the analysis of the working principle of serviceannotation beanpostprocessor. The working principle of ReferenceAnnotationBeanPostProcessor will be explained in the next article

 

@EnableDubbo annotation

 

There are also two annotations @ EnableDubboConfig and @ DubboComponentScan on this annotation.

Spring has provided the annotation function of annotations, which can realize the inheritance function of similar annotations. For example, the famous @ SpringBootApplication annotation of springboot. Therefore, the two annotations EnableDubboConfig and DubboComponentScan actually work.

@EnableDubboConfig annotation  


You can see the @ Import annotation, @ Import is a very important annotation for spring, and must be configured and used with the Configuration annotation before it will take effect. Therefore, you can deduce that the EnableDubbo annotation must also be used with the Configuration annotation.

The correction here has been found through my own test. I can cooperate with you@Component Annotations can also be used together.

@The Import annotation can realize the function of importing third-party package beans into the container. It can be used together with the annotation Configuration to realize the ability of injecting third-party beans with an annotation, that is, EnableDubbo. This annotation can identify the principle of whether dubbo is started or not.

You can see the parameter dubboconfigurationregistrar class of the @ Import annotation in the figure.

Dubboconfigurationregistrar class

 

As can be seen from the method name in the figure, three methods are injected into the bean container

registerBeans(registry, DubboConfigConfiguration.Single.class);

 /**
    * Register Beans if not present in {@link BeanDefinitionRegistry registry}
    *
    * @param registry         {@link BeanDefinitionRegistry}
    * @param annotatedClasses {@link Annotation annotation} class
    */
   public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {

       if (ObjectUtils.isEmpty(annotatedClasses)) {
           return;
       }

       Set<Class<?>> classesToRegister = new LinkedHashSet<Class<?>>(asList(annotatedClasses));

       // Remove all annotated-classes that have been registered
       Iterator<Class<?>> iterator = classesToRegister.iterator();

       while (iterator.hasNext()) {
           Class<?> annotatedClass = iterator.next();
           if (isPresentBean(registry, annotatedClass)) {
               iterator.remove();
           }
       }

       AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);

       if (logger.isDebugEnabled()) {
           logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
       }
   	//Here, the Class corresponding to the Class parameter d passed in by the package will be added to the container
       reader.register(classesToRegister.toArray(EMPTY_CLASS_ARRAY));

   }

The AnnotatedBeanDefinitionReader will be used in the source code to put the passed DubboConfigConfiguration.Single class into the container.

DubboConfigConfiguration.Single class

You can see that the EnableConfigurationBeanBinding annotation is used in the end. This annotation comes with Spring

 

Go back to the deep level. The ConfigurationBeanBindingRegistrar class has too much code. Only the key methods in the screenshot.

As can be seen from the source code, the type parameter passed in the EnableConfigurationBeanBinding annotation will be put into the container as BeanDefinition, and the value of the prefix parameter value in the configuration as the prefix of the configured key will be injected into this bean. As for how to inject configuration into beans, I still don't understand it. I need to find it later.

At this point dubbo dependent config Objects are all injected into the container. 
At the same time, some configuration information is injected into the correct database config Yes

@DubboComponentScan
The above is only to understand how some configuration objects of Dubbo are injected into the container, but how some services of Dubbo are injected into the container. Let's take a look at the source code of DubboComponentScan annotation.
Take a look at the dubbocomponentscanregister class

/**
 * Dubbo {@link DubboComponentScan} Bean Registrar
 *
 * @see Service
 * @see DubboComponentScan
 * @see ImportBeanDefinitionRegistrar
 * @see ServiceAnnotationBeanPostProcessor
 * @see ReferenceAnnotationBeanPostProcessor
 * @since 2.5.7
 */
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {

 

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //Look at the method name and guess to get the package path. Enter the following source code and have a look
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

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

    /**
     * Registers {@link ServiceAnnotationBeanPostProcessor}
     *
     * @param packagesToScan packages to scan without resolving placeholders
     * @param registry       {@link BeanDefinitionRegistry}
     * @since 2.5.8
     */
    private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
        //First put the bean of ServiceAnnotationBeanPostProcessor class into the container. And pass the path as a parameter into this class
        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
        builder.addConstructorArgValue(packagesToScan);
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);

    }
    /**
    *  Get the path information of the package to be scanned configured in the annotation
    */
    private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
        //Gets all attributes in the annotation
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                metadata.getAnnotationAttributes(DubboComponentScan.class.getName()));
               //Get configured path information
        String[] basePackages = attributes.getStringArray("basePackages");
        Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
        
        String[] value = attributes.getStringArray("value");
        // Appends value array attributes
        Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value));
        packagesToScan.addAll(Arrays.asList(basePackages));
        for (Class<?> basePackageClass : basePackageClasses) {
            packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
        }
        if (packagesToScan.isEmpty()) {
            return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
        }
        return packagesToScan;
    }

}

ServiceAnnotationBeanPostProcessor class
The ServiceAnnotationBeanPostProcessor class was explained in my last article
https://blog.csdn.net/leisurelen/article/details/106993692

The function of this class is to scan the incoming path and the annotations of all classes in the path. If there are DubboService and Service annotations, the corresponding Beandefinition will be generated and put into the container.

A prerequisite for understanding this class is the ClassPathBeanDefinitionScanner class, which is a Spring class used to scan specific annotation classes in the project and put this class into the container. Dubbo uses the function of this class to scan DubboService annotations in the project and generate BeanDefinition into the container.

Specific process:

1. Generate the BeanDefinition of event listener class dubbobootstrappapplicationlistener and put it into the container. This is new in @ since version 2.7.5
2. Resolve the incoming path under processing
3. Generate DubboClassPathBeanDefinitionScanner class to scan the classes under the path. This class inherits from the ClassPathBeanDefinitionScanner class. dubbo has not been greatly modified. It just passes in two objects: environment and resourceLoader. At the same time, two annotation filters DubboService and Service are added to the scanner, and the default filter of spring is disabled, that is, spring beans will not be scanned. The following figure shows that the incoming parameter disables useDefaultFilters.
org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner

4. Scan the classes under the path. At this time, the scanner will scan the DubboService and Service annotated classes into the container, and the normal classes of spring will not be scanned
5. Get all scanned beandefinitions put into the container. Traverse each beandefinition and get the first interface of the bean, generate a beandefinition of ServiceBean for each class, put it into the container, and inject some information of DubboService annotation into ServiceBean, and the first interface is also injected as attribute, Servicebeans inherit from the ServiceConfig class.
The source code of the method for generating servicebeans is at org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor#buildServiceBeanDefinition. I won't post it here.

Come here dubbo of Servcie The injection principle is clear,
In fact, the essence is generated for each class ServiceConfig Object.

Another question is how the Reference annotation works, which will be explained in the next article.
For dubbo's xml integration and spring mode, you can refer to

Statement:

Reprint the original text: https://blog.csdn.net/leisurelen/article/details/107019516

Copyright notice: This article is the original article of the original blogger and follows the CC 4.0 BY-SA copyright agreement. For reprint, please attach the source link of the original text and this notice. Reprint is only used for learning records. If there is infringement, please contact to delete.

Keywords: Java Dubbo Spring

Added by gardner1 on Tue, 23 Nov 2021 02:07:01 +0200