Dubbo学习之PostProcessor

导读:本篇文章讲解 Dubbo学习之PostProcessor,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

相关阅读

简介

本文基于Spring Boot 2.6.6dubbo-spring-boot-starter 3.0.6环境。

Dubbo中使用的BeanDefinitionRegistryPostProcessor如下:

  1. ServiceAnnotationPostProcessor,在DubboAutoConfiguration中以BeanMethod方式注册;
  2. DubboConfigAliasPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition
  3. DubboInfraBeanRegisterPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition

这三者都未实现PriorityOrderedOrdered接口,由ConfigurationClassPostProcessor(实现了PriorityOrdered)解析注册到容器中;


Dubbo中使用的BeanFactoryPostProcessor如下:

  1. ReferenceAnnotationBeanPostProcessor,间接实现了Ordered接口;

Dubbo中使用的BeanPostProcessor如下:

  1. DubboConfigDefaultPropertyValueBeanPostProcessor实现了PriorityOrdered接口,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition
  2. ReferenceAnnotationBeanPostProcessor实现了Ordered接口,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition
  3. DubboConfigAliasPostProcessor,在DubboBeanUtils.registerCommonBeans方法中注册RootBeanDefinition

DubboConfigDefaultPropertyValueBeanPostProcessorDubboConfigAliasPostProcessor的实例化是发生在AbstractApplicationContext。registerBeanPostProcessors方法中;
ReferenceAnnotationBeanPostProcessor的实例化是发生在DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory方法中,且在ReferenceAnnotationBeanPostProcessor.postProcessBeanFactory方法中会移除自身的RootBeanDefinition,以避免在AbstractApplicationContext。registerBeanPostProcessors方法中再次实例化;

BeanFactoryPostProcessor

ServiceAnnotationPostProcessor

postProcessBeanDefinitionRegistry方法中处理Dubbo Service注解标注的类,如:

@DubboService
public class DemoServiceImpl implements DemoService {
}

postProcessBeanFactory方法中处理Dubbo Service注解标注的Bean(标注在BeanMethod),如:

@Bean
@DubboService
public MethodServiceImpl methodService() {
    return new MethodServiceImpl();
}

同时,ServiceAnnotationPostProcessor也作为<dubbo:annotation package="" />标签的解析器,配置如下:

// DubboNamespaceHandler.java
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());


// AnnotationBeanDefinitionParser.java
protected Class<?> getBeanClass(Element element) {
    return ServiceAnnotationPostProcessor.class;
}

postProcessBeanDefinitionRegistry

代码如下:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    this.registry = registry;
    scanServiceBeans(resolvedPackagesToScan, registry);
}

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

    // 设置扫描标识,避免重复扫描
    scaned = true;
    if (CollectionUtils.isEmpty(packagesToScan)) {
        // 无路径需要扫描,则直接退出
        if (logger.isWarnEnabled()) {
            logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }
        return;
    }

    // 配置DubboClassPathBeanDefinitionScanner
    DubboClassPathBeanDefinitionScanner scanner =
            new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
    scanner.setBeanNameGenerator(beanNameGenerator);
    for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
    }

    ScanExcludeFilter scanExcludeFilter = new ScanExcludeFilter();
    scanner.addExcludeFilter(scanExcludeFilter);

    // 扫描各个包路径
    for (String packageToScan : packagesToScan) {

        // 如果已经扫描过则跳过
        if (servicePackagesHolder.isPackageScanned(packageToScan)) {
            if (logger.isInfoEnabled()) {
                logger.info("Ignore package who has already bean scanned: " + packageToScan);
            }
            continue;
        }

        // 扫描包路径下被Dubbo Service注解标注的类,并生成BeanDefinition
        scanner.scan(packageToScan);

        // 查找Dubbo Service的BeanDefinitionHolder
        // 结果会在scan中缓存,故此次直接从缓存中得到
        Set<BeanDefinitionHolder> beanDefinitionHolders =
                findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
            if (logger.isInfoEnabled()) {
                List<String> serviceClasses = new ArrayList<>(beanDefinitionHolders.size());
                for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                    serviceClasses.add(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
                }
                logger.info("Found " + beanDefinitionHolders.size() + " classes annotated by Dubbo @Service under package [" + packageToScan + "]: " + serviceClasses);
            }

            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                // 向容器中注册该beanDefinitionHolder
                processScannedBeanDefinition(beanDefinitionHolder, registry, scanner);
                // 缓存已扫描过的类
                servicePackagesHolder.addScannedClass(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
            }
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("No class annotated by Dubbo @Service was found under package ["
                        + packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount());
            }
        }

        // 缓存已扫描过的包路径
        servicePackagesHolder.addScannedPackage(packageToScan);
    }
}

主要逻辑为:

  1. 生成标注为Dubbo Service 的Class的BeanDefinition并注册到容器;
  2. 将生成的BeanDefinition,再次注册为Dubbo Service BeanDefinition

生成标注为Dubbo Service的BeanDefinition

ClassPathBeanDefinitionScanner.scan(packageToScan)内部使用doScan实现,其代码如下:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 查找满足要求的候选组件Dubbo Service Class
        // 对basePackage路径下所有类经过isCandidateComponent筛选
        //     先经过excludeFilters(优先),再经过includeFilters
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            // 校验当前容器是否已存在该BeanDefinition
            // 1. 若不存在则校验通过
            // 2. 若存在,但兼容,则校验不通过
            // 3. 若存在,且不兼容,则抛出异常
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 注册BeanDefinition,此时beanName根据原始类名生成
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

注册Dubbo Service BeanDefinition

processScannedBeanDefinition代码如下:

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

    Class<?> beanClass = resolveClass(beanDefinitionHolder);

    // 获取类上标注的Dubbo Service注解
    Annotation service = findServiceAnnotation(beanClass);

    // 获取注解的属性
    Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);

    String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);

    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

    // 构造Dubbo Service BeanName
    // ServiceBean:interfaceName
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);

    // 构造Dubbo Service BeanDefinition
    AbstractBeanDefinition serviceBeanDefinition =
            buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);

    // 注册Dubbo Service BeanDefinition
    // 此时beanName为ServiceBean:interfaceName
    registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);

}

postProcessBeanFactory

代码如下:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    if (this.registry == null) {
        // 未在postProcessBeanDefinitionRegistry中设置,则此时设置
        this.registry = (BeanDefinitionRegistry) beanFactory;
    }

    // 处理由标注了Dubbo Service注解的BeanMethod得到的BeanDefinition
    String[] beanNames = beanFactory.getBeanDefinitionNames();
    for (String beanName : beanNames) {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
        Map<String, Object> annotationAttributes = getServiceAnnotationAttributes(beanDefinition);
        // 存在则说明BeanMethod上存在Dubbo Service注解
        if (annotationAttributes != null) {
            // 注册为Dubbo Service BeanDefinition
            processAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition, annotationAttributes);
        }
    }

    if (!scaned) {
        // 还未扫描过,则扫描
        scanServiceBeans(resolvedPackagesToScan, registry);
    }
}

DubboConfigAliasPostProcessor

DubboConfigAliasPostProcessor核心功能是给AbstractConfig添加Alias,如果其id存在的话,该动作是在BeanPostProcessor.postProcessAfterInitialization方法中实现的,本文关注其接口BeanFactoryPostProcessor的实现,代码如下:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    this.registry = registry;
}

DubboInfraBeanRegisterPostProcessor

DubboInfraBeanRegisterPostProcessor用于实例化基础Bean,如:ReferenceAnnotationBeanPostProcessor
核心代码如下:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    this.registry = registry;
}

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    if (registry != null) {
        // 实例化ReferenceAnnotationBeanPostProcessor,用于处理ReferenceBean
        ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = beanFactory.getBean(
            ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
        beanFactory.addBeanPostProcessor(referenceAnnotationBeanPostProcessor);

        // 注册PropertySourcesPlaceholderConfigurer如果容器还不存在的话
        DubboBeanUtils.registerPlaceholderConfigurerBeanIfNotExists(beanFactory, registry);
    }

    ApplicationModel applicationModel = DubboBeanUtils.getApplicationModel(beanFactory);
    ModuleModel moduleModel = DubboBeanUtils.getModuleModel(beanFactory);

    // 设置applicationContext
    SpringExtensionInjector.get(applicationModel).init(applicationContext);
    SpringExtensionInjector.get(moduleModel).init(applicationContext);
    DubboBeanUtils.getInitializationContext(beanFactory).setApplicationContext(applicationContext);

    // 设置Dubbo配置参数
    ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();
    SortedMap<String, String> dubboProperties = EnvironmentUtils.filterDubboProperties(environment);
    applicationModel.getModelEnvironment().setAppConfigMap(dubboProperties);

    // 注册ConfigManager单例
    beanFactory.registerSingleton(ConfigManager.BEAN_NAME, applicationModel.getApplicationConfigManager());
}

BeanFactoryPostProcessor

ReferenceAnnotationBeanPostProcessor

ReferenceAnnotationBeanPostProcessor用于处理DubboReference注解,继承自AbstractAnnotationBeanPostProcessor,从而支持将ReferenceBean注入DubboReference注解标注的字段或者setter方法;同时实现了BeanFactoryPostProcessor接口,便于早期处理容器中已注册的Bean信息;
核心方法如下:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    String[] beanNames = beanFactory.getBeanDefinitionNames();
    for (String beanName : beanNames) {
        Class<?> beanType;
        if (beanFactory.isFactoryBean(beanName)){
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            if (isReferenceBean(beanDefinition)) {
                continue;
            }
            if (isAnnotatedReferenceBean(beanDefinition)) {
                // 处理BeanMethod上的DubboReference注解
                processReferenceAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition);
                continue;
            }

            String beanClassName = beanDefinition.getBeanClassName();
//                if (beanDefinition instanceof AnnotatedBeanDefinition) {
//                    AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
//                    beanClassName = annotatedBeanDefinition.getFactoryMethodMetadata().getDeclaringClassName();
//                }
            beanType = ClassUtils.resolveClass(beanClassName, getClassLoader());
        } else {
            beanType = beanFactory.getType(beanName);
        }
        if (beanType != null) {
            AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
            try {
                // 注入Dubbo Reference如果需要的话
                prepareInjection(metadata);
            } catch (BeansException e) {
                throw e;
            } catch (Exception e) {
                throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
            }
        }
    }

    if (beanFactory instanceof AbstractBeanFactory) {
        List<BeanPostProcessor> beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors();
        for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
            if (beanPostProcessor == this) {
                // 本BeanPostProcessor在DubboInfraBeanRegisterPostProcessor实例化,并注册为BeanPostProcessor
                // 不需要在PostProcessorRegistrationDelegate.registerBeanPostProcessors方法中再次注册
                // 那么会导致BeanPostProcessorChecker统计出错
                // 故此时移除BeanDefinition,这样在PostProcessorRegistrationDelegate.registerBeanPostProcessors方法中就不会被再注册
                beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
                break;
            }
        }
    }

    try {
        // 发布DubboConfigInitEvent事件,开始Dubbo初始化
        applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));
    } catch (Exception e) {
        logger.warn("publish early application event failed, please upgrade spring version to 4.2.x or later: " + e);
    }
}

BeanPostProcessor

DubboConfigDefaultPropertyValueBeanPostProcessor

DubboConfigDefaultPropertyValueBeanPostProcessor继承自GenericBeanPostProcessorAdapter<AbstractConfig>,故只会处理AbstractConfig Bean,主要是给AbstractConfig Bean设置id字段如果该字段还未赋值的话;
核心代码如下:

protected void processBeforeInitialization(AbstractConfig dubboConfigBean, String beanName) throws BeansException {
    if (!beanName.contains("#")) {
        // 设置id字段如果不存在的话
        setPropertyIfAbsent(dubboConfigBean, Constants.ID, beanName);

        // beanName should not be used as config name, fix https://github.com/apache/dubbo/pull/7624
        //setPropertyIfAbsent(dubboConfigBean, "name", beanName);
    }
}

protected void setPropertyIfAbsent(Object bean, String propertyName, String beanName) {

    Class<?> beanClass = getTargetClass(bean);

    PropertyDescriptor propertyDescriptor = getPropertyDescriptor(beanClass, propertyName);

    if (propertyDescriptor != null) {
        Method getterMethod = propertyDescriptor.getReadMethod();

        if (getterMethod == null) {
            return;
        }

        Object propertyValue = invokeMethod(getterMethod, bean);

        if (propertyValue != null) {
            // 字段值存在则无需操作
            return;
        }

        Method setterMethod = propertyDescriptor.getWriteMethod();
        if (setterMethod != null) {
            if (Arrays.equals(of(String.class), setterMethod.getParameterTypes())) {
                // 使用beanName作为该字段值
                invokeMethod(setterMethod, bean, beanName);
            }
        }
    }
}

ReferenceAnnotationBeanPostProcessor

对于BeanPostProcessor接口的方法,ReferenceAnnotationBeanPostProcessor没有特殊实现,ReferenceAnnotationBeanPostProcessor继承自AbstractAnnotationBeanPostProcessor是为了实现注入ReferenceBean功能;

DubboConfigAliasPostProcessor

DubboConfigAliasPostProcessor核心功能是给AbstractConfig Bean添加值为id字段的Alias,如果其id字段值存在的话;
核心代码如下:

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof AbstractConfig) {
        String id = ((AbstractConfig) bean).getId();
        if (hasText(id)
                && !nullSafeEquals(id, beanName)
                && !hasAlias(registry, beanName, id)) {
            // 注册别名:ID
            registry.registerAlias(beanName, id);
        }
    }
    return bean;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/4760.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!