zoukankan      html  css  js  c++  java
  • dubbo @service @dubboService解析

    老规矩,从框架的使用方式入手分析,类似mybatis,dubbo也有个扫描服务的注解:org.apache.dubbo.config.spring.context.annotation.DubboComponentScan

    同样地,配套一个@Import:org.apache.dubbo.config.spring.context.annotation.DubboComponentScanRegistrar,作用就是把BeanDefinitionRegistry交给你全权处理,

    对应这里就是构建一个org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor的BeanDefinition,然后加入BeanDefinitionRegistry。

    这是个BeanDefinitionRegistry后处理bean,主要逻辑在父类org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor,最新版本直接就用了父类。

    在如下dubbo springboot自动配置包中有个自动配置类,也是通过该后置bean解析@dubboService类的,不同的是,该自动配置的方式是从yaml获取服务类所在的包路径:

     自动配置类org.apache.dubbo.spring.boot.autoconfigure.DubboAutoConfiguration:

     

     对应yaml文件内容如下,这种方式配置的好处是可以把该配置项放到配置中心统一管理:

    下面我们具体看下这个类:

    实现了接口BeanDefinitionRegistryPostProcessor,对BeanDefinitionRegistry进行后处理,主要逻辑在org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor#registerServiceBeans方法:

    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 -> {
    // 设置扫描的包下被指定注解标注的类是需要处理的serviceAnnotationTypes包含如下几个注解
    // org.apache.dubbo.config.annotation.DubboService,2.7.7版本后直接用这个注解暴露服务
    // org.apache.dubbo.config.annotation.Service,@Deprecated
    // com.alibaba.dubbo.config.annotation.Service,@Deprecated scanner.addIncludeFilter(
    new AnnotationTypeFilter(annotationType)); }); for (String packageToScan : packagesToScan) { // 注册注解标注的类BeanDefinition // 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) {
    // 构建org.apache.dubbo.config.spring.ServiceBean对应的BeanDefinition并注册到BeandefinitionRegistry 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 + "]"); } } } }

     重点看下注册ServiceBean代码:

    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);
         // 服务接口类,可通过@DubboService的interfaceClass或者interfaceName指定,默认为注解标注类对应的接口class
            Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
    
            String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
            // 构建ServiceBean的BeanDefinition用于注册
            AbstractBeanDefinition serviceBeanDefinition =
                    buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);
    
            // ServiceBean Bean name
            String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
    
            if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
    // 注册ServiceBean的BeanDefinition
    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?"); } } }
    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
    // 指向标注@DubboService注解的原始Bean(在服务暴露的时候会用到)
    addPropertyReference(builder, "ref", annotatedServiceBeanName); // Set interface
    // 指向@DubboService配置的服务接口类名,默认为标注类的接口类(在服务暴露的时候会用到
    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); } /** * Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference */ String providerConfigBeanName = serviceAnnotationAttributes.getString("provider"); if (StringUtils.hasText(providerConfigBeanName)) { addPropertyReference(builder, "provider", providerConfigBeanName); } /** * Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference */ String monitorConfigBeanName = serviceAnnotationAttributes.getString("monitor"); if (StringUtils.hasText(monitorConfigBeanName)) { addPropertyReference(builder, "monitor", monitorConfigBeanName); } /** * Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference */ String applicationConfigBeanName = serviceAnnotationAttributes.getString("application"); if (StringUtils.hasText(applicationConfigBeanName)) { addPropertyReference(builder, "application", applicationConfigBeanName); } /** * Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference */ String moduleConfigBeanName = serviceAnnotationAttributes.getString("module"); if (StringUtils.hasText(moduleConfigBeanName)) { addPropertyReference(builder, "module", moduleConfigBeanName); } /** * Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference */ String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry"); List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames); if (!registryRuntimeBeanReferences.isEmpty()) { builder.addPropertyValue("registries", registryRuntimeBeanReferences); } /** * Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference */ String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol"); List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames); if (!protocolRuntimeBeanReferences.isEmpty()) { builder.addPropertyValue("protocols", protocolRuntimeBeanReferences); } return builder.getBeanDefinition(); }
  • 相关阅读:
    ubuntu12.04 死机 卡屏 画面冻结解决方案
    Install Firefox 20 in Ubuntu 13.04, Ubuntu 12.10, Ubuntu 12.04, Linux Mint 14 and Linux Mint 13 by PPA
    ListView1.SelectedItems.Clear()
    android studio 下载地址
    jquery.slider.js jquery幻灯片测试
    jquery.hovermenu.js
    jquery.tab.js选项卡效果
    适配 placeholder,jquery版
    jquery.autoscroll.js jquery自动滚动效果
    将 Google Earth 地图集成到自己的窗体上的 简单控件
  • 原文地址:https://www.cnblogs.com/reboot30/p/15089318.html
Copyright © 2011-2022 走看看