vlambda博客
学习文章列表

Dubbo 服务启动初始化注解实现源码分析

Dubbo的版本2.7.x,SpringBoot整合

概要

Dubbo 注解配置是基于 Spring 注解配置 的,巧妙地利用 Spring 进行配置简化。建议同学们优先去了解Spring 注解配置后阅读。

@EnableDubbo @EnableDubboConfig @DubboComponentScan 这三个注解位于 dubbo-config 模块的 dubbo-config-spring 项目下的 org.apache.dubbo.config.spring.context.annotation 包中,是主要的初始化配置注解。

@DubboService @DubboReference这二个注解位于 dubbo-common 模块的 dubbo-common 项目下的 org.apache.dubbo.config.annotation 包中,基于 @DubboComponentScan 扫描实现了初始化。

@EnableDubbo

@EnableDubbo 注解并未提供多余的功能仅是将 @DubboComponentScan 和 @EnableDubboConfig 组合起来方便用户使用,简单的看下代码。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {

    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};

    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
    boolean multipleConfig() default true;

}

@EnableDubboConfig

@EnableDubboConfig 注解的目的就是帮我们简化这些(ApplicationConfig、ModuleConfig、RegistryConfig、ProtocolConfig、MonitorConfig、ProviderConfig、ConsumerConfig 等)配置,只要将相应的配置项通过 .properties 文件交由 @PropertySource 注解由 Spring 加载到 Environment 中,Dubbo 即可通过 Environment 中相应的属性与 ApplicationConfig 对象同名的属性进行绑定,而这个过程都是自动的。本身代码中作者给出了注释,问题变得显而易见。

/**
 * As  a convenient and multiple {@link EnableDubboConfigBinding}
 * in default behavior , is equal to single bean bindings with below convention prefixes of properties:
 * <ul>
 * <li>{@link ApplicationConfig} binding to property : "dubbo.application"</li>
 * <li>{@link ModuleConfig} binding to property :  "dubbo.module"</li>
 * <li>{@link RegistryConfig} binding to property :  "dubbo.registry"</li>
 * <li>{@link ProtocolConfig} binding to property :  "dubbo.protocol"</li>
 * <li>{@link MonitorConfig} binding to property :  "dubbo.monitor"</li>
 * <li>{@link ProviderConfig} binding to property :  "dubbo.provider"</li>
 * <li>{@link ConsumerConfig} binding to property :  "dubbo.consumer"</li>
 * </ul>
 * <p>
 * In contrast, on multiple bean bindings that requires to set {@link #multiple()} to be <code>true</code> :
 * <ul>
 * <li>{@link ApplicationConfig} binding to property : "dubbo.applications"</li>
 * <li>{@link ModuleConfig} binding to property :  "dubbo.modules"</li>
 * <li>{@link RegistryConfig} binding to property :  "dubbo.registries"</li>
 * <li>{@link ProtocolConfig} binding to property :  "dubbo.protocols"</li>
 * <li>{@link MonitorConfig} binding to property :  "dubbo.monitors"</li>
 * <li>{@link ProviderConfig} binding to property :  "dubbo.providers"</li>
 * <li>{@link ConsumerConfig} binding to property :  "dubbo.consumers"</li>
 * </ul>
 *
 * @see EnableDubboConfigBinding
 * @see DubboConfigConfiguration
 * @see DubboConfigConfigurationRegistrar
 * @since 2.5.8
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {

    boolean multiple() default true;

}

DubboConfigConfigurationRegistrar

@EnableDubboConfig 背后的注册处理就是通过这个(@Import(DubboConfigConfigurationRegistrar.class)完成的,DubboConfigConfigurationRegistrar 继承实现于 Spring 提供的一个接口 ImportBeanDefinitionRegistrar,这个类会在 Spring 中注册两个对象 DubboConfigConfiguration.Single 和 DubboConfigConfiguration.Multiple,区分同一属性的单个配置和多个配置。

package org.springframework.context.annotation;

public interface ImportBeanDefinitionRegistrar {
    void registerBeanDefinitions(AnnotationMetadata var1, BeanDefinitionRegistry var2);
}
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        boolean multiple = attributes.getBoolean("multiple");

        registerBeans(registry, DubboConfigConfiguration.Single.class);

        if (multiple) {
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }

        registerCommonBeans(registry);
    }
}

DubboConfigConfiguration

查看 DubboConfigConfiguration 可知,Single 和 Multiple 本身并没有任何作用,区分了同一属性的单个配置和多个配置,只是它头上的 @EnableConfigurationBeanBinding 的注解背后的解析器 ConfigurationBeanBindingRegistrar 起了作用。

public class DubboConfigConfiguration {

    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.application"type = ApplicationConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.module"type = ModuleConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registry"type = RegistryConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocol"type = ProtocolConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitor"type = MonitorConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.provider"type = ProviderConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumer"type = ConsumerConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-center"type = ConfigCenterBean.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-report"type = MetadataReportConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metrics"type = MetricsConfig.class),
            @EnableConfigurationBeanBinding(prefix = "dubbo.ssl"type = SslConfig.class)
    })
    public static class Single {

    }

    @EnableConfigurationBeanBindings({
            @EnableConfigurationBeanBinding(prefix = "dubbo.applications"type = ApplicationConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.modules"type = ModuleConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.registries"type = RegistryConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.protocols"type = ProtocolConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.monitors"type = MonitorConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.providers"type = ProviderConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.consumers"type = ConsumerConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.config-centers"type = ConfigCenterBean.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metadata-reports"type = MetadataReportConfig.class, multiple = true),
            @EnableConfigurationBeanBinding(prefix = "dubbo.metricses"type = MetricsConfig.class, multiple = true)
    })
    public static class Multiple {

    }
}

@EnableConfigurationBeanBinding

@EnableConfigurationBeanBinding 注解 prefix 的值代表 .properties 文件配置项 key 的前缀,完整的 key 就会映射到 type 代表类的属性。

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ConfigurationBeanBindingRegistrar.class})
public @interface EnableConfigurationBeanBinding {
    boolean DEFAULT_MULTIPLE = false;
    boolean DEFAULT_IGNORE_UNKNOWN_FIELDS = true;
    boolean DEFAULT_IGNORE_INVALID_FIELDS = true;

    String prefix();

    Class<?> type();

    boolean multiple() default false;

    boolean ignoreUnknownFields() default true;

    boolean ignoreInvalidFields() default true;
}

ConfigurationBeanBindingRegistrar

ConfigurationBeanBindingRegistrar 读取 @EnableConfigurationBeanBinding 的 type 属性来注册 bean。

public class ConfigurationBeanBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    // ......
    

    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attributes = metadata.getAnnotationAttributes(ENABLE_CONFIGURATION_BINDING_CLASS_NAME);
        this.registerConfigurationBeanDefinitions(attributes, registry);
    }

    // 读取 @EnableConfigurationBeanBinding 里的各种属性
    public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {
        String prefix = (String)AnnotationUtils.getRequiredAttribute(attributes, "prefix");
        prefix = this.environment.resolvePlaceholders(prefix);
        Class<?> configClass = (Class)AnnotationUtils.getRequiredAttribute(attributes, "type");
        boolean multiple = (Boolean)AnnotationUtils.getAttribute(attributes, "multiple"false);
        boolean ignoreUnknownFields = (Boolean)AnnotationUtils.getAttribute(attributes, "ignoreUnknownFields"true);
        boolean ignoreInvalidFields = (Boolean)AnnotationUtils.getAttribute(attributes, "ignoreInvalidFields"true);
        this.registerConfigurationBeans(prefix, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, registry);
    }

    // 根据 type 属性来批量注册 bean
    private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple, boolean ignoreUnknownFields, boolean ignoreInvalidFields, BeanDefinitionRegistry registry) {
        Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(this.environment.getPropertySources(), this.environment, prefix);
        if (CollectionUtils.isEmpty(configurationProperties)) {
            if (this.log.isDebugEnabled()) {
                this.log.debug("There is no property for binding to configuration class [" + configClass.getName() + "] within prefix [" + prefix + "]");
            }

        } else {
            Set<String> beanNames = multiple ? this.resolveMultipleBeanNames(configurationProperties) : Collections.singleton(this.resolveSingleBeanName(configurationProperties, configClass, registry));
            Iterator var9 = beanNames.iterator();

            while(var9.hasNext()) {
                String beanName = (String)var9.next();
                this.registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, configurationProperties, registry);
            }

            // 注册 bean 实例化前后逻辑
            this.registerConfigurationBindingBeanPostProcessor(registry);
        }
    }
    
    // 实际单个 bean 注册逻辑
    private void registerConfigurationBean(String beanName, Class<?> configClass, boolean multiple, boolean ignoreUnknownFields, boolean ignoreInvalidFields, Map<String, Object> configurationProperties, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configClass);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        this.setSource(beanDefinition);
        Map<String, Object> subProperties = this.resolveSubProperties(multiple, beanName, configurationProperties);
        ConfigurationBeanBindingPostProcessor.initBeanMetadataAttributes(beanDefinition, subProperties, ignoreUnknownFields, ignoreInvalidFields);
        registry.registerBeanDefinition(beanName, beanDefinition);
        if (this.log.isInfoEnabled()) {
            this.log.info("The configuration bean definition [name : " + beanName + ", content : " + beanDefinition + "] has been registered.");
        }

    }
    
    // 选用 ConfigurationBeanBindingPostProcessor 完成注册逻辑增强
    private void registerConfigurationBindingBeanPostProcessor(BeanDefinitionRegistry registry) {
        BeanRegistrar.registerInfrastructureBean(registry, "configurationBeanBindingPostProcessor", ConfigurationBeanBindingPostProcessor.class);
    }
    
    // ......
    
}

ConfigurationBeanBindingPostProcessor

ConfigurationBeanBindingPostProcessor 继承实现于 Spring 提供的一个接口 BeanPostProcessor,BeanPostProcessor 是 Spring IOC 容器给我们提供的一个扩展接口,在 Spring 容器中完成 bean 实例化、配置以及其他初始化方法前后添加一些自己处理逻辑,调用 postProcessBeforeInitialization() 方法来进行数据绑定。

package org.springframework.beans.factory.config;

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;

    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}
public class ConfigurationBeanBindingPostProcessor implements BeanPostProcessor, BeanFactoryAware {

    // ......
    
    // 调用 postProcessBeforeInitialization() 方法来进行数据绑定
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        BeanDefinition beanDefinition = this.getNullableBeanDefinition(beanName);
        if (this.isConfigurationBean(bean, beanDefinition)) {
            this.bindConfigurationBean(bean, beanDefinition);
            this.customize(beanName, bean);
        }

        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    // ......
    
    // 数据绑定过程
    private void bindConfigurationBean(Object configurationBean, BeanDefinition beanDefinition) {
        Map<String, Object> configurationProperties = getConfigurationProperties(beanDefinition);
        boolean ignoreUnknownFields = getIgnoreUnknownFields(beanDefinition);
        boolean ignoreInvalidFields = getIgnoreInvalidFields(beanDefinition);
        this.getConfigurationBeanBinder().bind(configurationProperties, ignoreUnknownFields, ignoreInvalidFields, configurationBean);
        if (this.log.isInfoEnabled()) {
            this.log.info("The configuration bean [" + configurationBean + "] have been binding by the configuration properties [" + configurationProperties + "]");
        }

    }

    private void customize(String beanName, Object configurationBean) {
        Iterator var3 = this.getConfigurationBeanCustomizers().iterator();

        while(var3.hasNext()) {
            ConfigurationBeanCustomizer customizer = (ConfigurationBeanCustomizer)var3.next();
            customizer.customize(beanName, configurationBean);
        }

    }

    // ......
    
    public ConfigurationBeanBinder getConfigurationBeanBinder() {
        if (this.configurationBeanBinder == null) {
            this.initConfigurationBeanBinder();
        }

        return this.configurationBeanBinder;
    }
    
    private void initConfigurationBeanBinder() {
        if (this.configurationBeanBinder == null) {
            try {
                this.configurationBeanBinder = (ConfigurationBeanBinder)this.beanFactory.getBean(ConfigurationBeanBinder.class);
            } catch (BeansException var2) {
                if (this.log.isInfoEnabled()) {
                    this.log.info("configurationBeanBinder Bean can't be found in ApplicationContext.");
                }

                this.configurationBeanBinder = this.defaultConfigurationBeanBinder();
            }
        }
    }
    
    // ......

}

@DubboComponentScan

@DubboComponentScan 是 Dubbo 组件扫描注释,扫描类路径以获取将自动注册为 Spring bean 的注释组件,背后的处理器是 DubboComponentScanRegistrar。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {

    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

}

DubboComponentScanRegistrar

DubboComponentScanRegistrar 继承实现于 Spring 提供的一个接口 ImportBeanDefinitionRegistrar。registerServiceAnnotationBeanPostProcessor() 方法注册一个 ServiceAnnotationBeanPostProcessor,用来扫描 @Service,registerCommonBeans() 方法用来为使用@Reference 等的 Bean 注册。

package org.springframework.context.annotation;

public interface ImportBeanDefinitionRegistrar {
    void registerBeanDefinitions(AnnotationMetadata var1, BeanDefinitionRegistry var2);
}

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
        
        registerCommonBeans(registry);
    }

    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);

    }

    // 根据配置的包路径扫描
    private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                metadata.getAnnotationAttributes(DubboComponentScan.class.getName()));
        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;
    }

}

@DubboService

ServiceAnnotationBeanPostProcessor

ServiceAnnotationBeanPostProcessor 类已被弃用,其新的实现查看 ServiceClassPostProcessor。

@Deprecated
public class ServiceAnnotationBeanPostProcessor extends ServiceClassPostProcessor {
    // ......
}

ServiceClassPostProcessor 继承实现于 Spring 提供的一个接口BeanDefinitionRegistryPostProcessor。当 ServiceClassPostProcessor 的 postProcessBeanDefinitionRegistry() 方法调用时,会扫描 Spring 的 @Service 注解、Dubbo 的 @Service 注解和 @DubboService 注解的类并注册为 Spring Bean。

package org.springframework.beans.factory.support;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
        ResourceLoaderAware, BeanClassLoaderAware {

    // 扫描 Spring 的 @Service 注解、Dubbo 的 @Service 注解和 @DubboService 注解
    private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
            DubboService.class,
            Service.class,
            com.alibaba.dubbo.config.annotation.Service.class
    );

    // ......
    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        registerBeans(registry, DubboBootstrapApplicationListener.class);

        Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);

        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            registerServiceBeans(resolvedPackagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
            }
        }

    }
    
    // ......
}

registerServiceBeans() 方法中除了将 @Service 注解的类注册为 Spring Bean,内部还调用 registerServiceBean() 方法注册一个 ServiceBean,这个对象内部有个 ref 属性指向 @Service 类 bean。

    /**
     * Registers {@link ServiceBean} from new annotated {@link Service} {@link BeanDefinition}
     *
     * @param beanDefinitionHolder
     * @param registry
     * @param scanner
     * @see ServiceBean
     * @see BeanDefinition
     */
    private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {

        Class<?> beanClass = resolveClass(beanDefinitionHolder);

        Annotation service = findServiceAnnotation(beanClass);

        AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, falsefalse);

        Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);

        String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

        // 注册定义一个 ServiceBean
        AbstractBeanDefinition serviceBeanDefinition =
                buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

        // ServiceBean Bean name
        String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

        if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
            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?");
            }
        }

    }

ServiceBean

ServiceBean 继承于 ServiceConfig,并且实现了 InitializingBean 接口,在 afterPropertiesSet() 方法被调用的时候会通过 applicationContext 查找 Dubbo Provider 需要的配置,而这些配置早已通过@EnableDubboConfig 注册到了 Spring 中,完整的 ServiceBean 实例化就完成了。

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
        ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware {
        
    // ......
    
    @Override
    public void afterPropertiesSet() throws Exception {
        if (StringUtils.isEmpty(getPath())) {
            if (StringUtils.isNotEmpty(beanName)
                    && StringUtils.isNotEmpty(getInterface())
                    && beanName.startsWith(getInterface())) {
                setPath(beanName);
            }
        }
    }
    
}

@DubboReference

ReferenceAnnotationBeanPostProcessor

ReferenceAnnotationBeanPostProcessor 继承实现于 Spring 提供的一个抽象类 AbstractAnnotationBeanPostProcessor。当 ReferenceAnnotationBeanPostProcessor 的 doGetInjectedBean() 方法调用时,会扫描 Spring 的 @Reference 注解、Dubbo 的 @Reference 注解和 @DubboReference 注解并通过 JDK 动态代理创建一个代理对象,这个代理对象的目标对象是 ReferenceBean,这个 ReferenceBean 继承于在 API 配置中提到的 ReferenceConfig。

package com.alibaba.spring.beans.factory.annotation;

public abstract class AbstractAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
    // ......
}
public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements
        ApplicationContextAware, ApplicationListener<ServiceBeanExportedEvent> {

    // ......
    
    // 扫描 Spring 的 @Reference 注解、Dubbo 的 @Reference 注解和 @DubboReference 注解
    public ReferenceAnnotationBeanPostProcessor() {
        super(
        DubboReference.class, 
        Reference.class, 
        com.alibaba.dubbo.config.annotation.Reference.class);
    }

    // ......
    
    @Override
    protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {

        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

        String referenceBeanName = getReferenceBeanName(attributes, injectedType);

         // 注册定义一个 ReferenceBean
        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

        boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

        registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

        cacheInjectedReferenceBean(referenceBean, injectedElement);

        // 通过 JDK 动态代理创建一个代理对象
        return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
    }
    
    // ......
    
    private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes, Class<?> referencedType) throws Exception {
        // 如果多个地方使用 @Reference 引用同一个服务,需要看他们的的缓存 key 是否一样,
        // 如果都是一样的,那么就只会创建一个 ReferenceBean
        ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);
        if (referenceBean == null) {
            ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
                    .create(attributes, applicationContext)
                    .interfaceClass(referencedType);
            referenceBean = beanBuilder.build();
            referenceBeanCache.put(referenceBeanName, referenceBean);
        } else if (!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
            throw new IllegalArgumentException("reference bean name " + referenceBeanName + " has been duplicated, but interfaceClass " +
                    referenceBean.getInterfaceClass().getName() + " cannot be assigned to " + referencedType.getName());
        }
        return referenceBean;
    }
    
    private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean, AnnotationAttributes attributes, boolean localServiceBean, Class<?> interfaceClass) {

        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        String beanName = getReferenceBeanName(attributes, interfaceClass);

        if (localServiceBean) {
            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
            RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref");
            String serviceBeanName = runtimeBeanReference.getBeanName();
            beanFactory.registerAlias(serviceBeanName, beanName);
        } else {
            if (!beanFactory.containsBean(beanName)) {
                beanFactory.registerSingleton(beanName, referenceBean);
            }
        }
    }
    
    private void cacheInjectedReferenceBean(ReferenceBean referenceBean, InjectionMetadata.InjectedElement injectedElement) {
        if (injectedElement.getMember() instanceof Field) {
            injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
        } else if (injectedElement.getMember() instanceof Method) {
            injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
        }
    }

    private Object getOrCreateProxy(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean, Class<?> serviceInterfaceType) {
        if (localServiceBean) {
            return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
                    newReferencedBeanInvocationHandler(referencedBeanName));
        } else {
            exportServiceBeanIfNecessary(referencedBeanName); 
            return referenceBean.get();
        }
    }
    
    // ......
    
}

ReferenceBean

ReferenceBean 是通过 ReferenceBeanBuilder 的 build() 方法,首先通过 doBuild() 方法 new 一个空ReferenceBean 对象,然后调用 configureBean() 方法完成这个空对象的配置。

public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
        ApplicationContextAware, InitializingBean, DisposableBean {
        
    // ......
    
    @Override
    public void afterPropertiesSet() throws Exception {
    
        prepareDubboConfigBeans();

        if (init == null) {
            init = false;
        
        if (shouldInit()) {
            getObject();
        }
    }
    
    private void prepareDubboConfigBeans() {
        beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class);
        beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, SslConfig.class);
    }
}

DubboBeanUtils

DubboBeanUtils 在 DubboConfigConfigurationRegistrar,DubboComponentScanRegistrar 中都有被调用到。DubboBeanUtils 使用的 registerInfrastructureBean() 方法其实就是调用 BeanRegistrar.registerInfrastructureBean() 方法来进行数据绑定。

public interface DubboBeanUtils {

    /**
     * Register the common beans
     *
     * @param registry {@link BeanDefinitionRegistry}
     * @see ReferenceAnnotationBeanPostProcessor
     * @see DubboConfigDefaultPropertyValueBeanPostProcessor
     * @see DubboConfigAliasPostProcessor
     * @see DubboLifecycleComponentApplicationListener
     * @see DubboBootstrapApplicationListener
     */
    static void registerCommonBeans(BeanDefinitionRegistry registry) {
    
        registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
                ReferenceAnnotationBeanPostProcessor.class);

        registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
                DubboConfigAliasPostProcessor.class);

        registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
                DubboLifecycleComponentApplicationListener.class);
                
        registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
                DubboBootstrapApplicationListener.class);

        registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
                DubboConfigDefaultPropertyValueBeanPostProcessor.class);
    }
}

BeanRegistrar

BeanRegistrar.registerInfrastructureBean() 方法是抽象出一个通过 bean 定义、bean 处理器名称和 bean 处理器类型三个参数为注册 bean 数据绑定的一个公共方法。提取了如 ReferenceAnnotationBeanPostProcessor,DubboConfigAliasPostProcessor 等多种处理器的数据绑定公共部分逻辑。

public abstract class BeanRegistrar {

    // ......
    
    public static boolean registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry, String beanName, Class<?> beanType) {
        boolean registered = false;
        if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
            beanDefinition.setRole(2);
            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
            registered = true;
            if (log.isInfoEnabled()) {
                log.info("The Infrastructure bean definition [" + beanDefinition + "with name [" + beanName + "] has been registered.");
            }
        }

        return registered;
    }
    
    // ......
    
}