dubbo 源码解析(一)

本文解析的Dubbo源码的版本为2.7.9

1 与spring整合源码

1.1 注册Dubbo配置类

在这里插入图片描述

上图为Dubbo与Spring整合注册配置类的主要流程,下面我们一步步来分析。
Dubbo与Spring整合首先我们会在启动类上配置 @EnableDubbo注解,

@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和@DubboComponentScan两个注解,@EnableDubboConfig注解的作用就是将Dubbo的一些配置类注册到Spring种,而@DubboComponentScan则是注册扫描@Service注解和@Reference注解的bean工厂后置处理器。
下面进入@EnableDubboConfig注解类

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {
    
    boolean multiple() default true;
}

该注解类上使用了注解@Import,导入了DubboConfigConfigurationRegistrar类,该类实现了ImportBeanDefinitionRegistrar,所以会在启动的时候执行其registerBeanDefinitions。

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar, ApplicationContextAware {

    private ConfigurableApplicationContext applicationContext;

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

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

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

        /**
         * 注册DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple,
         * 该类中配置了需要注册的配置类
         * 及配置类的属性对应的值在配置文件种的前缀
         */
        // Single Config Bindings
        registerBeans(registry, DubboConfigConfiguration.Single.class);

        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }

        // Since 2.7.6
        registerCommonBeans(registry);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (!(applicationContext instanceof ConfigurableApplicationContext)) {
            throw new IllegalArgumentException("The argument of ApplicationContext must be ConfigurableApplicationContext");
        }
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }
}

在registerBeanDefinitions方法中注册了DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple两个类。
注意在EnableDubboConfig注解中有一个属性multiple,默认是true,为true的时候才会注册DubboConfigConfiguration.Multiple类,这个类会解析复数形式的配置,即同一类型的配置类可能会注册多个。

dubbo.applications.p1.name=dubbo-server1
dubbo.applications.p2.name=dubbo-server2

如上配置会注册两个ApplicationConfig类到Spring容器中,beanName分别为p1和p2。
下面查看DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple源码

@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 {

    }

    /**
     * Multiple Dubbo {@link AbstractConfig Config} Bean Binding
     */
    @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 {

    }

这两个类中都是空的,类上面都配置了@EnableConfigurationBeanBindings注解,注解里配置了Dubbo配置类的类型,以及该配置类对应的配置前缀。下面我们进入该注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigurationBeanBindingsRegister.class)
public @interface EnableConfigurationBeanBindings {

    /**
     * @return the array of {@link EnableConfigurationBeanBinding EnableConfigurationBeanBindings}
     */
    EnableConfigurationBeanBinding[] value();
}

可以看到EnableConfigurationBeanBindings注解上又使用了@Import注解,导入了ConfigurationBeanBindingsRegister,我们看其registerBeanDefinitions方法

public class ConfigurationBeanBindingsRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private ConfigurableEnvironment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		/**
		 * 获取DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple类上的
		 * EnableConfigurationBeanBindings注解配置的属性
		 */
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableConfigurationBeanBindings.class.getName()));

        AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");

        ConfigurationBeanBindingRegistrar registrar = new ConfigurationBeanBindingRegistrar();

        registrar.setEnvironment(environment);

        for (AnnotationAttributes element : annotationAttributes) {
        	/**
        	 * 根据@EnableConfigurationBeanBindings注解配置的属性注册配置类
        	 * 配置类中的属性的值来源于Spring的environment即我们在配置文件中配置的值
        	 */
            registrar.registerConfigurationBeanDefinitions(element, registry);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        this.environment = (ConfigurableEnvironment) environment;
    }
}

该方法中首先获取了DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple类上@EnableConfigurationBeanBindings注解配置的属性,根据配置的属性通过ConfigurationBeanBindingRegistrar 类来注册属性上配置的配置类,调用的是其registerConfigurationBeanDefinitions方法,ConfigurationBeanBindingRegistrar类主要方法如下

public class ConfigurationBeanBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    final static Class ENABLE_CONFIGURATION_BINDING_CLASS = EnableConfigurationBeanBinding.class;

    private final static String ENABLE_CONFIGURATION_BINDING_CLASS_NAME = ENABLE_CONFIGURATION_BINDING_CLASS.getName();


    public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {

		/**
		 * 获取@EnableConfigurationBeanBindings注解中属性配置的前缀,比如dubbo.appliation
		 */
        String prefix = getRequiredAttribute(attributes, "prefix");

        prefix = environment.resolvePlaceholders(prefix);
		/**
		 * 获取@EnableConfigurationBeanBindings注解中配置的Dubbo配置类类型
		 * 比如ApplicationConfig.class
		 */
        Class<?> configClass = getRequiredAttribute(attributes, "type");

        boolean multiple = getAttribute(attributes, "multiple", valueOf(DEFAULT_MULTIPLE));

        boolean ignoreUnknownFields = getAttribute(attributes, "ignoreUnknownFields", valueOf(DEFAULT_IGNORE_UNKNOWN_FIELDS));

        boolean ignoreInvalidFields = getAttribute(attributes, "ignoreInvalidFields", valueOf(DEFAULT_IGNORE_INVALID_FIELDS));

        registerConfigurationBeans(prefix, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, registry);
    }


    private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple,
                                            boolean ignoreUnknownFields, boolean ignoreInvalidFields,
                                            BeanDefinitionRegistry registry) {

		/**
		 * 根据配置的前缀,获取配置文件中配置的属性值以key-value的形式存入map中
		 * 如配置的dubbo.application.name=dubbo-server,对应map中为name->dubbo-server
		 * 如果配置的为复数dubbo.applications.p1.name=dubbo-server1,对应map中p1.name->dubbo-server1
		 */
        Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(environment.getPropertySources(), environment, prefix);

		/**
		 * 如果根据前缀在配置文件中获取到的map为空则直接返回,不注册前缀对应的配置类。
		 */
        if (CollectionUtils.isEmpty(configurationProperties)) {
            if (log.isDebugEnabled()) {
                log.debug("There is no property for binding to configuration class [" + configClass.getName()
                        + "] within prefix [" + prefix + "]");
            }
            return;
        }

		/**
		 * 获取beanName,如果是配置单数的情况,则自动生成beanname
		 * 如果配置双数的情况,如dubbo.applications.p1.name,则p1则为beanName
		 */
        Set<String> beanNames = multiple ? resolveMultipleBeanNames(configurationProperties) :
                singleton(resolveSingleBeanName(configurationProperties, configClass, registry));

		/**
		 * 根据beanName注册配置类,配置复数形式,则同一配置类会注册多个bean
		 */
        for (String beanName : beanNames) {
            registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields,
                    configurationProperties, registry);
        }

		/**
		 * 注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性
		 */
        registerConfigurationBindingBeanPostProcessor(registry);
    }

    private void registerConfigurationBean(String beanName, Class<?> configClass, boolean multiple,
                                           boolean ignoreUnknownFields, boolean ignoreInvalidFields,
                                           Map<String, Object> configurationProperties,
                                           BeanDefinitionRegistry registry) {
		
		/**
		 * 根据配置类类型创建一个BeanDefinition.
		 */
        BeanDefinitionBuilder builder = rootBeanDefinition(configClass);

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

		/**
		 * 给BeanDefinition设置source属性,这个值很重要,因为bean的后置处理其会处理所有的bean,
		 * ConfigurationBeanBindingPostProcessor这个bean的后置处理器,
		 * 就是通过这个属性来判断该类是dubbo的一个配置类,从而注入属性,过滤其它的bean。
		 */
        setSource(beanDefinition);

		/**
		 * 获取配置类的属性配置
		 * 如果是单数形式,则直接返回configurationProperties
		 * 如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
		 */
        Map<String, Object> subProperties = resolveSubProperties(multiple, beanName, configurationProperties);

		/**
		 * 给BeanDefinition设置属性,如subProperties
		 * 后置处理器ConfigurationBeanBindingPostProcessor会取从BeanDefinition中取得属性subProperties,给配置类实例赋值。
		 */
        initBeanMetadataAttributes(beanDefinition, subProperties, ignoreUnknownFields, ignoreInvalidFields);

        registry.registerBeanDefinition(beanName, beanDefinition);

        if (log.isInfoEnabled()) {
            log.info("The configuration bean definition [name : " + beanName + ", content : " + beanDefinition
                    + "] has been registered.");
        }
    }

		/**
		 * 获取配置类的属性配置
		 * 如果是单数形式,则直接返回configurationProperties
		 * 如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
		 */
    private Map<String, Object> resolveSubProperties(boolean multiple, String beanName,
                                                     Map<String, Object> configurationProperties) {
        if (!multiple) {
            return configurationProperties;
        }

        MutablePropertySources propertySources = new MutablePropertySources();

        propertySources.addLast(new MapPropertySource("_", configurationProperties));

        return getSubProperties(propertySources, environment, normalizePrefix(beanName));
    }

    private void setSource(AbstractBeanDefinition beanDefinition) {
        beanDefinition.setSource(ENABLE_CONFIGURATION_BINDING_CLASS);
    }

	/**
	 * 注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性
	 */
    private void registerConfigurationBindingBeanPostProcessor(BeanDefinitionRegistry registry) {
        registerInfrastructureBean(registry, ConfigurationBeanBindingPostProcessor.BEAN_NAME,
                ConfigurationBeanBindingPostProcessor.class);
    }

}

首先看registerConfigurationBeanDefinitions方法,该方法就是获取@EnableConfigurationBeanBindings注解中属性配置,比如配置类类型等,然后调用registerConfigurationBeans方法。

registerConfigurationBeans:
1.根据配置的前缀,获取配置文件中配置的属性值以key-value的形式存入map中。如配置的dubbo.application.name=dubbo-server,对应map中为name->dubbo-server;如果配置的为复数dubbo.applications.p1.name=dubbo-server1,对应map中p1.name->dubbo-server1。
2.如果根据前缀在配置文件中获取到的map为空则直接返回,不注册前缀对应的配置类。
3.获取beanName,如果是配置单数的情况,则自动生成beanName,如果配置双数的情况,如dubbo.applications.p1.name,则p1则为beanName
4.根据beanName注册配置类,配置复数形式,则同一配置类会注册多个bean,即调用registerConfigurationBean方法。
5.注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性

registerConfigurationBean:
1.根据配置类类型创建一个BeanDefinition。
2.给BeanDefinition设置source属性,这个值很重要,因为bean的后置处理其会处理所有的bean,ConfigurationBeanBindingPostProcessor这个bean的后置处理器,就是通过这个属性来判断该类是dubbo的一个配置类,从而注入属性,过滤其它的bean。
3.获取配置类的属性配置如果是单数形式,则直接返回configurationProperties;如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
4.给BeanDefinition设置属性,如subProperties,后置处理器ConfigurationBeanBindingPostProcessor会从BeanDefinition中取得属性subProperties,给配置类实例赋值。
5.注册BeanDefinition。

1.2 注册ServiceBean和ReferenceBean

在这里插入图片描述
上图是注册ServiceBean和ReferenceBean的主要流程,下面详细分析源码
ServiceBean和ReferenceBean的注册是通过EnableDubbo注解类上@DubboComponentScan注解来完成的,而@DubboComponentScan注解上又有@Import(DubboComponentScanRegistrar.class)注解,下面查看DubboComponentScanRegistrar类,spring启动会调用其registerBeanDefinitions方法

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {

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

        /**
         *  获取@EnableDubbo注解上配置的扫描包的路径
         *  如果未配置,则使用注解所修饰的配置类所在包路径。
         */
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        /**
         * 注册bean工厂的后置处理器ServiceAnnotationBeanPostProcessor
         * 该bean工厂的后置处理器的作用是扫描@Service注解所在类,注册到spring中
         * 并注册一个对应的ServiceBean到spring中
         */
        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) {

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

}

该类完成了3件事情:
1.获取扫描包的路径,如果@EnableDubbo注解上配置了扫描包的路径,则使用配置路径;如果未配置,则使用注解所修饰的配置类所在包路径。
2.注册了一个bean工厂的后置处理器ServiceAnnotationBeanPostProcessor,扫描@Service注解
3.注册了一个bean的后置处理器ReferenceAnnotationBeanPostProcessor,扫描@Reference。

1.2.1 ServiceAnnotationBeanPostProcessor 扫描@Service

ServiceAnnotationBeanPostProcessor类里什么也没做,主要逻辑是在其父类ServiceClassPostProcessor里完成的,该类是一个bean工厂的后置处理其,会执行其postProcessBeanDefinitionRegistry方法。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        /**
         * 注册DubboBootstrapApplicationListener这是一个ApplicationListener
         * spring容器启动完成后会执行其onApplicationContextEvent方法
         * 调用所有注册了的ServiceBean的exported方法,完成服务导出
         */
        // @since 2.7.5
        registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);

        /**
         * 获取传入的扫描包路径
         */
        Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);

        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            /**
             * 注册@Service修饰的类到spring中,并注册对应的ServiceBean到spring中
             */
            registerServiceBeans(resolvedPackagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
            }
        }

    }

该方法中:

  1. 注册了一个ApplicationListener的实现DubboBootstrapApplicationListener,这个listener很重要,spring容器启动完成后会执行其onApplicationContextEvent方法,调用所有注册了的ServiceBean的exported方法,完成服务导出。
  2. 调用registerServiceBeans方法注册@Service修饰的类到spring中,并注册对应的ServiceBean到spring中。

下面我们进入registerServiceBeans方法

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

        /**
         *  创建一个扫描包的扫描器
         */
        DubboClassPathBeanDefinitionScanner scanner =
                new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

        /**
         * 获取一个beanName的生成器
         */
        BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

        scanner.setBeanNameGenerator(beanNameGenerator);

        /**
         * 添加扫描注解的filter
         */
        // refactor @since 2.7.7
        serviceAnnotationTypes.forEach(annotationType -> {
            scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
        });

        for (String packageToScan : packagesToScan) {

            /**
             * 将@Service注解的类注册的spring中
             */
            // 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) {
                    /**
                     * 注册相应的ServiceBean到spring中
                     */
                    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 + "]");
                }

            }

        }

    }

该方法中:
1.创建一个扫描包的扫描器DubboClassPathBeanDefinitionScanner,该类继承了ClassPathBeanDefinitionScanner,将useDefaultFilters设置为false,默认的过滤器是扫描@Component注解的,并设置了beanName生成器BeanNameGenerator,给扫描器添加了扫描@Service注解的AnnotationTypeFilter过滤器。
2.调用DubboClassPathBeanDefinitionScanner的scan方法将@Service所在类注册到Spring容器,改方法为Spring逻辑这里不做深究。
3.获取到DubboClassPathBeanDefinitionScanner注册的所有BeanDefinition,调用registerServiceBean注册ServiceBean。

registerServiceBean方法如下:

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

        Class<?> beanClass = resolveClass(beanDefinitionHolder);

        Annotation service = findServiceAnnotation(beanClass);

        /**
         * 获取@Service注解的所有属性
         */
        AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);

        /**
         * 获取服务的接口
         */
        Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
		/**
         * 服务实现类的beanName
         */
        String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

        /**
         *  创建ServiceBean的BeanDefinition
         */
        AbstractBeanDefinition serviceBeanDefinition =
                buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

        /**
         * 根据InterfaceClass、group、version生成ServiceBean的beanName
         */
        // 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?");
            }

        }

    }

该方法中:

  1. 首先获取@Service注解的所有属性
  2. 创建ServiceBean的BeanDefinition
  3. 根据InterfaceClass、group、version生成ServiceBean的beanName,并注册ServiceBean到Spring容器中。

注意:在ServiceBean的顶层父类中有AbstractConfig中,有一个
addIntoConfigManager方法上添加了注解@PostConstruct,所以该方法会在Bean的初始化时调用

@PostConstruct
    public void addIntoConfigManager() {
        ApplicationModel.getConfigManager().addConfig(this);
    }

该方法通过dubbo得SPI获得一个单例的ConfigManager,将ServiceBean的实例添加到configsCache中。

1.2.1.1 DubboBootstrapApplicationListener 服务导出

Spring容器启动后会调用其onApplicationContextEvent方法,该方法中调用了onContextRefreshedEvent方法

private void onContextRefreshedEvent(ContextRefreshedEvent event) {
        dubboBootstrap.start();
    }

服务导出就是在DubboBootstrap 类的start方法中完成的,start方法调用了exportServices方法

private void exportServices() {
		/**
         * 遍历configsCache中所有的ServiceBean实例
         * 执行其exported方法
         */
        configManager.getServices().forEach(sc -> {
            // TODO, compatible with ServiceConfig.export()
            ServiceConfig serviceConfig = (ServiceConfig) sc;
            serviceConfig.setBootstrap(this);

            if (exportAsync) {
                ExecutorService executor = executorRepository.getServiceExporterExecutor();
                Future<?> future = executor.submit(() -> {
                    sc.export();
                    exportedServices.add(sc);
                });
                asyncExportingFutures.add(future);
            } else {
                sc.export();
                exportedServices.add(sc);
            }
        });
    }

该方法中通过ConfigManager的getServices获取到所有的ServiceBean实例,最终就是从configsCache中拿到的实例,而通过上面的分析我们知道,在ServiceBean的初始化时会将实例放入单例的ConfigManager的configsCache中。

1.2.2 ReferenceAnnotationBeanPostProcessor 扫描@Reference

ReferenceAnnotationBeanPostProcessor 继承了AbstractAnnotationBeanPostProcessor类,该类属于InstantiationAwareBeanPostProcessor,在spring的bean属性注入populate方法中会调用其postProcessPropertyValues方法

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
		/**
		 * 扫描bean中被@Reference修饰的属性和方法,得到AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata对象
		 * 每个被@Reference修饰得属性和方法都会被封装为AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement或AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement对象
		 */
        InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
        try {
        	/**
        	 * 调用AnnotatedFieldElement或AnnotatedMethodElement的inject方法,完成ReferenceBean的生成和代理对象的注入。
        	 */
            metadata.inject(bean, beanName, pvs);
        } catch (BeanCreationException ex) {
            throw ex;
        } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
                    + " dependencies is failed", ex);
        }
        return pvs;
    }

该放发中:

  1. 扫描bean中被@Reference修饰的属性和方法,得到AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata对象,每个被@Reference修饰得属性和方法都会被封装为AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement或AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement对象。
  2. 调用AnnotatedFieldElement或AnnotatedMethodElement的inject方法,完成ReferenceBean的生成和代理对象的注入。

AnnotatedFieldElement方法的inject方法如下:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Class<?> injectedType = resolveInjectedType(bean, field);
            /**
             * 获取到依赖注入的代理对象
             */
            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

            ReflectionUtils.makeAccessible(field);
            /**
             * 反射给注入属性值
             */
            field.set(bean, injectedObject);

        }

AnnotatedMethodElement方法的inject方法如下:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Class<?> injectedType = pd.getPropertyType();
			/**
             * 获取到依赖注入的代理对象
             */
            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

            ReflectionUtils.makeAccessible(method);
			/**
             * 反射调用方法
             */
            method.invoke(bean, injectedObject);

        }

由上面看出获取到注入的代理对象,都是通过getInjectedObject方法获取的。

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

        String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
		/**
		 * 从缓存中injectedObjectsCache中获取代理对象
		 * 如果被引入过,就会存到injectedObjectsCache缓存中
		 */
        Object injectedObject = injectedObjectsCache.get(cacheKey);

        if (injectedObject == null) {
            injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
            // Customized inject-object if necessary
            injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
        }

        return injectedObject;

    }

该方法中首先会从缓存injectedObjectsCache中,拿代理对象,如果为null再调用doGetInjectedBean方法获取代理对象,最后存到缓存中。

下面进入doGetInjectedBean,该方法属于ReferenceAnnotationBeanPostProcessor,生成ReferenceBean和注册,就是在该方法中完成的。

protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {
        /**
         * 通过接口类型和注解的group、version得到对应得ServiceBean在spring中得beanName
         */
        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

        /**
         * 根据接口类型和@Reference注解中的属性,生成一个ReferenceBean在spring中的beanName
         */
        String referenceBeanName = getReferenceBeanName(attributes, injectedType);

        /**
         * 根据referenceBeanName从referenceBeanCache中拿ReferenceBean
         * 如果不存在则创建,并放入referenceBeanCache中
         */
        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

        /**
         * 判断服务是否是本地服务
         */
        boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

        /**
         * 如果是本地服务,判断是否导出,若未导出,则执行ServiceBean的exported方法导出服务
         */
        prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);

        /**
         * 如果是本地服务,则给本地服务的实现类注册一个别名,别名为referencedBeanName
         *      这样就和引用关联上
         * 如果是远程服务,则将ReferenceBean注册到Spring容器中
         */
        registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

        /**
         * 缓存注入的ReferenceBean
         */
        cacheInjectedReferenceBean(referenceBean, injectedElement);

        return referenceBean.get();
    }

该方法的每一步在代码中都有注释,此处不作解释,注意最后调用的referenceBean.get(),实际是调用的ReferenceConfig的get方法获取到的代理对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值