config module for dubbo source research

   Description of dubbo module:
   dubbo-common public logic module, including Util class and common model.
   dubbo-remoting remote communication module, equivalent to the implementation of the Dubbo protocol, if the RPC uses the RMI protocol, this package is not required.
   The dubbo-rpc remote call module, abstracting various protocols, and dynamic proxy, only includes one-to-one calls, and does not care about cluster management.
   The dubbo-cluster cluster module disguises multiple service providers as one provider, including: load balancing, fault tolerance, routing, etc. The address list of the cluster can be statically configured or issued by the registry.
   The dubbo-registry registry module, based on the clustering method of addresses issued by the registry, and the abstraction of various registries.
   The dubbo-monitor monitoring module, which counts the number of service calls, the call time, and the service tracked by the call chain.
   The dubbo-config configuration module is Dubbo's external API. Users can use Dubbo through Config to hide all the details of Dubbo.
   The dubbo-container container module is a Standlone container that loads Spring Boot with a simple Main, because services usually do not need the features of web containers such as Tomcat/JBoss, so there is no need to use a web container to load services.
  Today, I started to study the config module from the dubbo entry.
   The config module and the Service module are APIs, and the others are SPI implementations.
   config module uml class diagram

  The AbstractConfig class provides several main methods appendAnnotation, appendProperties, appendParameters, appendAttributes and
  other subclasses provide their own attributes.
  In the AbstractConfig class, a large number of related values ​​are obtained through reflection and javabean conventions. Special attention is paid to the defensive fault tolerance mentioned in the toString method annotation.
     catch (Throwable t) { // Defensive fault tolerance
            logger.warn(t.getMessage(), t);
            return super.toString();
        }


  Defensive fault tolerance is used here to improve code robustness.
  AnnotationBean is a special class in the subclass. Because this class is under the com.alibaba.dubbo.config.spring package.
This class belongs to the spring extension of the config module and supports the configuration of dubbo through annotations.
  AnnotationBean implements the four interfaces DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, and ApplicationContextAware.
   DisposableBean: Resource cleanup interface
   BeanFactoryPostProcessor, BeanPostProcessor: Similar in function, they are all extended interfaces after the bean is created.
   ApplicationContextAware: Get the spring context interface.
   It can be seen from this class that the dubbo annotation is actually an extension of the spring annotation, that is to say, the premise of using the dubbo annotation is to use the spring as the dubbo container.
   @servcie exposes code for dubbo service configuration
  
  public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        if (! isMatchPackage(bean)) {
            return bean;
        }
        Class<?> clazz = bean.getClass();
        if(isProxyBean(bean)){
            clazz = AopUtils.getTargetClass(bean);
        }
        Service service = clazz.getAnnotation(Service.class);
        if (service != null) {
            ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service);
            if (void.class.equals(service.interfaceClass())
                    && "".equals(service.interfaceName())) {
                if (clazz.getInterfaces().length > 0) {
                    serviceConfig.setInterface(clazz.getInterfaces()[0]);
                } else {
                    throw new IllegalStateException("Failed to export remote service class " + clazz.getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces.");
                }
            }
            if (applicationContext != null) {
                serviceConfig.setApplicationContext(applicationContext);
                if (service.registry() != null && service.registry().length > 0) {
                    List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
                    for (String registryId : service.registry()) {
                        if (registryId != null && registryId.length() > 0) {
                            registryConfigs.add((RegistryConfig)applicationContext.getBean(registryId, RegistryConfig.class));
                        }
                    }
                    serviceConfig.setRegistries(registryConfigs);
                }
                if (service.provider() != null && service.provider().length() > 0) {
                    serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(),ProviderConfig.class));
                }
                if (service.monitor() != null && service.monitor().length() > 0) {
                    serviceConfig.setMonitor((MonitorConfig)applicationContext.getBean(service.monitor(), MonitorConfig.class));
                }
                if (service.application() != null && service.application().length() > 0) {
                    serviceConfig.setApplication((ApplicationConfig)applicationContext.getBean(service.application(), ApplicationConfig.class));
                }
                if (service.module() != null && service.module().length() > 0) {
                    serviceConfig.setModule((ModuleConfig)applicationContext.getBean(service.module(), ModuleConfig.class));
                }
                if (service.provider() != null && service.provider().length() > 0) {
                    serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(), ProviderConfig.class));
                } else {
                    
                }
                if (service.protocol() != null && service.protocol().length > 0) {
                    List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
                    // modified by lishen; fix dubbo's bug
                    for (String protocolId : service.protocol()) {
                        if (protocolId != null && protocolId.length() > 0) {
                            protocolConfigs.add((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class));
                        }
                    }
                    serviceConfig.setProtocols(protocolConfigs);
                }
                try {
                    serviceConfig.afterPropertiesSet();
                } catch (RuntimeException e) {
                    throw (RuntimeException) e;
                } catch (Exception e) {
                    throw new IllegalStateException(e.getMessage(), e);
                }
            }
            serviceConfig.setRef(bean);
            serviceConfigs.add(serviceConfig);
            serviceConfig.export();
        }
        return bean;
    }

   The main thing is to first obtain the @servcie annotation on the class, and then create a new corresponding ServiceBean, which inherits from ServiceConfig, and implements the related interfaces of spring bean InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware.
   Finally, the serviceBean is stored in a thread-safe container.
   @service parsing is in postProcessAfterInitialization
   @Reference parsing is in postProcessBeforeInitialization, and the timing of the two is different.
  
   String key = reference.group() + "/" + interfaceName + ":" + reference.version();
        ReferenceBean<?> referenceConfig = referenceConfigs.get(key);

  As can be seen from this code, the uniqueness of the service interface is determined by group, interfaceName and vesion.
 
  

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326592131&siteId=291194637