3、Dubbo Spring整合原理分析

烟雨 4年前 (2021-12-23) 阅读数 841 #Dubbo
文章标签 Dubbo

Dubbo Spring整合原理整体流程图

234234.png

image.png

dubbo-provider.properties内容如下:

dubbo.application.name=dubbo-demo-provider1-application
dubbo.application.logger=log4j

dubbo.protocols.p1.name=dubbo
dubbo.protocols.p1.port=20880
dubbo.protocols.p1.host=0.0.0.0

dubbo.protocols.p2.name=dubbo
dubbo.protocols.p2.port=20881
dubbo.protocols.p2.host=0.0.0.0

dubbo.registries.r1.address=zookeeper://127.0.0.1:2181
dubbo.config-center.address=zookeeper://127.0.0.1:2181
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181

 Application应⽤启动类与配置如下:

public class Application {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();

        System.in.read();
    }

    @Configuration
    @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    static class ProviderConfiguration {
    }
}
应⽤配置类为ProviderConfiguration, 在配置上有两个⽐较重要的注解
  1. @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")表示对指定包下的类进⾏扫描,扫描@Service与@Reference注解,并且进⾏解析。

  2. @PropertySource表示将dubbo-provider.properties中的配置项添加到Spring容器中,可以通过@Value的⽅式获取到配置项中的值。

在EnableDubbo注解上,有另外两个重要的注解,@EnableDubboConfig@DubboComponentScan

image.png

一、@EnableDubboConfig注解

该注解是对properties⽂件进行解析的。

@EnableDubboConfig

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

    /**
     * It indicates whether binding to multiple Spring Beans.
     *
     * @return the default value is <code>false</code>
     * @revised 2.5.9
     */
    boolean multiple() default true;

}

@DubboComponentScan

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
	//省略
}
注意两个注解中对应的@Import注解所导⼊的类:
  1. DubboConfigConfigurationRegistrar

  2. DubboComponentScanRegistrar

Spring在启动时会解析这两个注解,并且执⾏对应的Registrar类中的registerBeanDefinitions()⽅法(这是Spring中提供的扩展功能)。

1.1、DubboConfigConfigurationRegistrar

234234.png

DubboConfigConfigurationRegistrar的主要作⽤就是对propties⽂件进⾏解析并根据不同的配置项项⽣成对应类型的Bean对象。

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

        // Single Config Bindings
        registerBeans(registry, DubboConfigConfiguration.Single.class);
        // multiple默认为true
        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }
    }
}
Spring启动时,会调⽤DubboConfigConfigurationRegistrar的registerBeanDefinitions()⽅法,该⽅法是利⽤Spring中的AnnotatedBeanDefinitionReader来读取:
  1. DubboConfigConfiguration.Single.class

  2. DubboConfigConfiguration.Multiple.class

这两个类上的注解。注解内容如下:
public class DubboConfigConfiguration {

    /**
     * Single Dubbo {@link AbstractConfig Config} Bean Binding
     * prefix:prefix中的内容为properties文件里面内容的前缀
     * type:表示解析后放在xxxConfig类中
     */
    @EnableDubboConfigBindings({
            @EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
            @EnableDubboConfigBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
            @EnableDubboConfigBinding(prefix = "dubbo.metrics", type = MetricsConfig.class)
    })
    public static class Single {

    }

    /**
     * Multiple Dubbo {@link AbstractConfig Config} Bean Binding
     */
    @EnableDubboConfigBindings({
            @EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
            @EnableDubboConfigBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
    })
    public static class Multiple {

    }
}
@EnableDubboConfigBinding中的内容解释:
  1. prefix:prefix中的内容为properties文件里面内容的前缀。

  2. type:表示解析后放在xxxConfig类中。

1.1.1、@EnableDubboConfigBindings

注意@EnableDubboConfigBindings,该类声明中也有个@Import注解,填写了一个DubboConfigBindingsRegistrar.class。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboConfigBindingsRegistrar.class)
public @interface EnableDubboConfigBindings {

    /**
     * The value of {@link EnableDubboConfigBindings}
     *
     * @return non-null
     */
    EnableDubboConfigBinding[] value();

}

1.1.2、DubboConfigBindingsRegistrar

该类会获取@EnableDubboConfigBindings注解中的value(也就是多个@EnableDubboConfigBinding注解),然后利用DubboConfigBindingRegistrar去处理这些@EnableDubboConfigBinding注解
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private final Log log = LogFactory.getLog(getClass());

    private ConfigurableEnvironment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //System.out.println("执行DubboConfigBindingRegistrar");
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName()));
        registerBeanDefinitions(attributes, registry);

    }

    protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) {
        // prefix = "dubbo.application"
        String prefix = environment.resolvePlaceholders(attributes.getString("prefix"));
        // type = ApplicationConfig.class
        Class<? extends AbstractConfig> configClass = attributes.getClass("type");
        boolean multiple = attributes.getBoolean("multiple");
        registerDubboConfigBeans(prefix, configClass, multiple, registry);

    }

    private void registerDubboConfigBeans(String prefix,
                                          Class<? extends AbstractConfig> configClass,
                                          boolean multiple,
                                          BeanDefinitionRegistry registry) {

        // 从properties文件中根据前缀拿对应的配置项,比如根据dubbo.application前缀,
        // 就可以拿到配置文件中的内容:
        // dubbo.application.name=dubbo-demo-provider-application
        // dubbo.application.logger=log4j
        Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix);

        // 如果没有相关的配置项,则不需要注册BeanDefinition
        if (CollectionUtils.isEmpty(properties)) {
            if (log.isDebugEnabled()) {
                log.debug("There is no property for binding to dubbo config class [" + configClass.getName()
                        + "] within prefix [" + prefix + "]");
            }
            return;
        }

        // 根据配置项生成beanNames,为什么会有多个?
        // 普通情况一个dubbo.application前缀对应一个ApplicationConfig类型的Bean
        // 特殊情况下,比如dubbo.protocols对应了:
        // dubbo.protocols.p1.name=dubbo
        // dubbo.protocols.p1.port=20880
        // dubbo.protocols.p1.host=0.0.0.0

        // dubbo.protocols.p2.name=http
        // dubbo.protocols.p2.port=8082
        // dubbo.protocols.p2.host=0.0.0.0
        // 那么就需要对应两个ProtocolConfig类型的Bean,那么就需要两个beanName:p1和p2

        // 这里就是multiple为true或false的区别,名字的区别,根据multiple用来判断是否从配置项中获取beanName
        // 如果multiple为false,则看有没有配置id属性,如果没有配置则自动生成一个beanName.
        Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) :
                Collections.singleton(resolveSingleBeanName(properties, configClass, registry));

        for (String beanName : beanNames) {
            // 为每个beanName,注册一个空的BeanDefinition
            registerDubboConfigBean(beanName, configClass, registry);
            // 为每个bean注册一个DubboConfigBindingBeanPostProcessor的Bean后置处理器,为BeanDefinition赋值
            registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry);

        }

        // 注册一个NamePropertyDefaultValueDubboConfigBeanCustomizer的bean
        registerDubboConfigBeanCustomizers(registry);

    }

    private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,
                                         BeanDefinitionRegistry registry) {

        BeanDefinitionBuilder builder = rootBeanDefinition(configClass);

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        // ApplicatinoConfig对象
        registry.registerBeanDefinition(beanName, beanDefinition);

        if (log.isInfoEnabled()) {
            log.info("The dubbo config bean definition [name : " + beanName + ", class : " + configClass.getName() +
                    "] has been registered.");
        }

    }

    private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple,
                                                             BeanDefinitionRegistry registry) {

        // 注册一个DubboConfigBindingBeanPostProcessor的Bean
        // 每个XxConfig的Bean对应一个DubboConfigBindingBeanPostProcessor的Bean。
        // 比如,一个ApplicationConfig对应一个DubboConfigBindingBeanPostProcessor,
        // 一个ProtocolConfig也会对应一个DubboConfigBindingBeanPostProcessor
        // 在构造DubboConfigBindingBeanPostProcessor的时候会指定构造方法的值,这样就可以区别开来了。
        Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class;

        BeanDefinitionBuilder builder = rootBeanDefinition(processorClass);

        // 真实的前缀,比如dubbo.registries.r2
        String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix;

        // 添加两个构造方法参数值,所以会调用DubboConfigBindingBeanPostProcessor的两个参数的构造方法
        builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

        registerWithGeneratedName(beanDefinition, registry);

        if (log.isInfoEnabled()) {
            log.info("The BeanPostProcessor bean definition [" + processorClass.getName()
                    + "] for dubbo config bean [name : " + beanName + "] has been registered.");
        }

    }

    private void registerDubboConfigBeanCustomizers(BeanDefinitionRegistry registry) {
        registerInfrastructureBean(registry, BEAN_NAME, NamePropertyDefaultValueDubboConfigBeanCustomizer.class);
    }

    @Override
    public void setEnvironment(Environment environment) {

        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);

        this.environment = (ConfigurableEnvironment) environment;

    }

    private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) {

        Set<String> beanNames = new LinkedHashSet<String>();

        // 比如dubbo.protocols.p1.name=dubbo的propertyName为p1.name

        for (String propertyName : properties.keySet()) {

            // propertyName为p1.name
            int index = propertyName.indexOf(".");

            if (index > 0) {

                // 截取beanName名字为p1
                String beanName = propertyName.substring(0, index);

                beanNames.add(beanName);
            }

        }

        return beanNames;

    }

    private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,
                                         BeanDefinitionRegistry registry) {

        // 配置了dubbo.application.id=appl,那么appl就是beanName
        String beanName = (String) properties.get("id");
        // 如果beanName为null,则会进入if分支,由spring自动生成一个beanName,比如org.apache.dubbo.config.ApplicationConfig#0
        if (!StringUtils.hasText(beanName)) {
            BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
            beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);
        }

        return beanName;

    }

}
DubboConfigBindingRegistrar类的主要功能就是获取⽤户所设置的properties文件中的内容,对Properties文件进行解析,根据Properties文件的每个配置项的前缀、参数名、参数值生成对应的BeanDefinition
比如:
dubbo.application.name=dubbo-demo-provider1-application
dubbo.application.logger=log4j
会生成前缀为"dubbo.application"的配置项,会⽣成⼀个ApplicationConfig类型的BeanDefinition,并且name和logger属性为对应的值。并且还会针对⽣成的每个BeanDefinition⽣成⼀个和它⼀对⼀绑定的BeanPostProcessor,类型为DubboConfigBindingBeanPostProcessor.class(上面代码67行)。

1.1.3、DubboConfigBindingBeanPostProcessor

public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware, InitializingBean
        , BeanDefinitionRegistryPostProcessor {

    private final Log log = LogFactory.getLog(getClass());

    /**
     * The prefix of Configuration Properties
     */
    private final String prefix;

    /**
     * Binding Bean Name
     */
    private final String beanName;

    private DubboConfigBinder dubboConfigBinder;

    private ApplicationContext applicationContext;

    private BeanDefinitionRegistry beanDefinitionRegistry;

    private boolean ignoreUnknownFields = true;

    private boolean ignoreInvalidFields = true;

    private List<DubboConfigBeanCustomizer> configBeanCustomizers = Collections.emptyList();

    /**
     * @param prefix   the prefix of Configuration Properties
     * @param beanName the binding Bean Name
     */
    public DubboConfigBindingBeanPostProcessor(String prefix, String beanName) {
        Assert.notNull(prefix, "The prefix of Configuration Properties must not be null");
        Assert.notNull(beanName, "The name of bean must not be null");
        this.prefix = prefix;
        this.beanName = beanName;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 每个XxConfig对应一个BeanPostProcessor,所以每个DubboConfigBindingBeanPostProcessor只处理对应的beanName
        if (this.beanName.equals(beanName) && bean instanceof AbstractConfig) {
            AbstractConfig dubboConfig = (AbstractConfig) bean;
            // 从properties文件中获取值,并设置到dubboConfig对象中
            bind(prefix, dubboConfig);
            // 设置dubboConfig对象的name属性,设置为beanName
            customize(beanName, dubboConfig);
        }
        return bean;
    }

    private void bind(String prefix, AbstractConfig dubboConfig) {

        dubboConfigBinder.bind(prefix, dubboConfig);

        if (log.isInfoEnabled()) {
            log.info("The properties of bean [name : " + beanName + "] have been binding by prefix of " +
                    "configuration properties : " + prefix);
        }
    }

    private void customize(String beanName, AbstractConfig dubboConfig) {

        for (DubboConfigBeanCustomizer customizer : configBeanCustomizers) {
            customizer.customize(beanName, dubboConfig);
        }

    }

    public boolean isIgnoreUnknownFields() {
        return ignoreUnknownFields;
    }

    public void setIgnoreUnknownFields(boolean ignoreUnknownFields) {
        this.ignoreUnknownFields = ignoreUnknownFields;
    }

    public boolean isIgnoreInvalidFields() {
        return ignoreInvalidFields;
    }

    public void setIgnoreInvalidFields(boolean ignoreInvalidFields) {
        this.ignoreInvalidFields = ignoreInvalidFields;
    }

    public DubboConfigBinder getDubboConfigBinder() {
        return dubboConfigBinder;
    }

    public void setDubboConfigBinder(DubboConfigBinder dubboConfigBinder) {
        this.dubboConfigBinder = dubboConfigBinder;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof AbstractConfig) {
            // 添加别名,id属性的值为别名

            String id = ((AbstractConfig) bean).getId();
            if (beanDefinitionRegistry != null && beanDefinitionRegistry instanceof DefaultListableBeanFactory) {
                DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanDefinitionRegistry;
                if (!StringUtils.isBlank(id) && !factory.hasAlias(beanName, id)) {
                    beanDefinitionRegistry.registerAlias(beanName, id);
                }
            }
        }
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 创建DefaultDubboConfigBinder
        initDubboConfigBinder();
        initConfigBeanCustomizers();
    }

    private void initDubboConfigBinder() {
        if (dubboConfigBinder == null) {
            try {
                // 先从Spring容器中获取DubboConfigBinder,默认获取不到
                dubboConfigBinder = applicationContext.getBean(DubboConfigBinder.class);
            } catch (BeansException ignored) {
                if (log.isDebugEnabled()) {
                    log.debug("DubboConfigBinder Bean can't be found in ApplicationContext.");
                }

                // Use Default implementation
                // 生成一个默认的
                dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment());
            }
        }

        dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields);
        dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields);

    }

    private void initConfigBeanCustomizers() {
        // 得到之前创建了的NamePropertyDefaultValueDubboConfigBeanCustomizer
        Collection<DubboConfigBeanCustomizer> configBeanCustomizers =
                beansOfTypeIncludingAncestors(applicationContext, DubboConfigBeanCustomizer.class).values();

        this.configBeanCustomizers = new ArrayList<>(configBeanCustomizers);

        AnnotationAwareOrderComparator.sort(this.configBeanCustomizers);
    }

    /**
     * Create {@link DubboConfigBinder} instance.
     *
     * @param environment
     * @return {@link DefaultDubboConfigBinder}
     */
    protected DubboConfigBinder createDubboConfigBinder(Environment environment) {
        DefaultDubboConfigBinder defaultDubboConfigBinder = new DefaultDubboConfigBinder();
        defaultDubboConfigBinder.setEnvironment(environment);
        return defaultDubboConfigBinder;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        if (this.beanDefinitionRegistry == null) {
            this.beanDefinitionRegistry = registry;
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //do nothing here
    }
}
DubboConfigBindingBeanPostProcessor是⼀个BeanPostProcessor,在Spring启动过程中,会针对所有的Bean对象进⾏后置加⼯。
但是在DubboConfigBindingBeanPostProcessor中有如下if判断:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 每个XxConfig对应一个BeanPostProcessor,所以每个DubboConfigBindingBeanPostProcessor只处理对应的beanName
    if (this.beanName.equals(beanName) && bean instanceof AbstractConfig) {
        AbstractConfig dubboConfig = (AbstractConfig) bean;
        // 从properties文件中获取值,并设置到dubboConfig对象中
        bind(prefix, dubboConfig);
        // 设置dubboConfig对象的name属性,设置为beanName
        customize(beanName, dubboConfig);
    }
    return bean;
}
所以DubboConfigBindingBeanPostProcessor并不会处理Spring容器中的所有Bean,它只会处理上⽂由Dubbo所⽣成的Bean对象。并且,在afterPropertiesSet()⽅法中,会先创建⼀个DefaultDubboConfigBinder。
@Override
public void afterPropertiesSet() throws Exception {
    // 创建DefaultDubboConfigBinder
    initDubboConfigBinder();
    initConfigBeanCustomizers();
}

1.1.4、DefaultDubboConfigBinder

当某个AbstractConfig类型的Bean,在经过DubboConfigBindingBeanPostProcessor处理时,此时Bean对象中的属性是没有值的,会利⽤DefaultDubboConfigBinder进⾏赋值。底层就是利⽤Spring中的DataBinder技术,结合properties⽂件对对应的属性进⾏赋值。
private void initDubboConfigBinder() {
    if (dubboConfigBinder == null) {
        try {
            // 先从Spring容器中获取DubboConfigBinder,默认会获取不到
            dubboConfigBinder = applicationContext.getBean(DubboConfigBinder.class);
        } catch (BeansException ignored) {
            if (log.isDebugEnabled()) {
                log.debug("DubboConfigBinder Bean can't be found in ApplicationContext.");
            }
            // Use Default implementation
            // 生成一个默认的
            dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment());
        }
    }
    dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields);
    dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields);
}

例如:

dubbo.application.name=dubbo-demo-provider1-application
dubbo.application.logger=log4j

对于上面配置,它对应ApplicationConfig对象(beanName是⾃动⽣成),最终ApplicationConfig对象的name属性的值为“dubbo-demo-provider1-application”,logger属性的值为“log4j"。

dubbo.protocols.p1.name=dubbo
dubbo.protocols.p1.port=20880
dubbo.protocols.p1.host=0.0.0.0
它对应ProtocolConfig对象(beanName为p1),最终ProtocolConfig对象的name属性的值为“dubbo”,port属性的值为20880,host属性的值为“0.0.0.0”。

1.2、DubboComponentScanRegistrar

处理dubbo的@Service注解

234234.png

DubboConfigConfigurationRegistrar的作⽤是向Spring容器中注册两个Bean。

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("执行DubboComponentScanRegistrar");

        // 拿到DubboComponentScan注解所定义的包路径,扫描该package下的类,识别这些类上
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        // 注册ServiceAnnotationBeanPostProcessor一个Bean
        // 实现了BeanDefinitionRegistryPostProcessor接口,所以在Spring启动时会调用postProcessBeanDefinitionRegistry方法
        // 该方法会进行扫描,扫描@Service注解了的类,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),后续的Spring周期中会生成Bean
        // 在ServiceBean中会监听ContextRefreshedEvent事件,一旦Spring启动完后,就会进行服务导出
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

        // 注册ReferenceAnnotationBeanPostProcessor
        // 实现了AnnotationInjectedBeanPostProcessor接口,继而实现了InstantiationAwareBeanPostProcessorAdapter接口
        // 所以Spring在启动时,在对属性进行注入时会调用AnnotationInjectedBeanPostProcessor接口中的postProcessPropertyValues方法
        // 在这个过程中会按照@Refrence注解的信息去生成一个RefrenceBean对象
        registerReferenceAnnotationBeanPostProcessor(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) {
        // 生成一个RootBeanDefinition,对应的beanClass为ServiceAnnotationBeanPostProcessor.class
        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
        // 将包路径作为在构造ServiceAnnotationBeanPostProcessor时调用构造方法时的传入参数
        builder.addConstructorArgValue(packagesToScan);
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);

    }

    /**
     * Registers {@link ReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
     *
     * @param registry {@link BeanDefinitionRegistry}
     */
    private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {

        // Register @Reference Annotation Bean Processor
        // 注册一个ReferenceAnnotationBeanPostProcessor做为bean,ReferenceAnnotationBeanPostProcessor是一个BeanPostProcessor
        BeanRegistrar.registerInfrastructureBean(registry,
                ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);

    }

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

}

1.2.1、ServiceAnnotationBeanPostProcessor

ServiceAnnotationBeanPostProcessor是⼀个BeanDefinitionRegistryPostProcessor,是⽤来注册BeanDefinition的。
它的主要作⽤是扫描Dubbo的@Service注解,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),在ServiceBean中会监听ContextRefreshedEvent事件(ServiceBean继承了ApplicationListener<ContextRefreshedEvent>),一旦Spring启动完后,就会进行服务导出。
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
    if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
        // 扫描包,进行Bean注册
        registerServiceBeans(resolvedPackagesToScan, registry);
    } else {
        if (logger.isWarnEnabled()) {
            logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }
    }
}

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
    DubboClassPathBeanDefinitionScanner scanner =
        new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
    scanner.setBeanNameGenerator(beanNameGenerator);

    // 扫描被Service注解标注的类
    scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
    /**
      * Add the compatibility for legacy Dubbo's @Service
      *
      * The issue : https://github.com/apache/dubbo/issues/4330
      * @since 2.7.3
      */
    scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class));

    for (String packageToScan : packagesToScan) {
        // Registers @Service Bean first
        // 扫描Dubbo自定义的@Service注解
        scanner.scan(packageToScan);
        // 查找被@Service注解的类的BeanDefinition(无论这个类有没有被@ComponentScan注解标注了)
        // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
        Set<BeanDefinitionHolder> beanDefinitionHolders =
            findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
            // 扫描到BeanDefinition开始处理它
            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                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 + "]");
            }
        }
    }
}

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {
    // 处理扫描到的每一个BeanDefinition
    // 1. 得到@Service注解上所配置的参数
    // 2. 根据每一个BeanDefinition会再额外的生成一个ServiceBean
    // 3. 对于每一个被@Service注解的类(服务的实现类),会生成两个Bean,
    //       一个服务实现类对应的Bean(普通Bean,和@Component一样),一个ServiceBean(Dubbo中要用到的Bean,因为在ServiceBean中包括了很的Config)
    // 具体的服务实现类
    Class<?> beanClass = resolveClass(beanDefinitionHolder);
    // @Service可以对服务进行各种配置
    Annotation service = findServiceAnnotation(beanClass);

    /**
     * The {@link AnnotationAttributes} of @Service annotation
     */
    AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);

    // 服务实现类对应的接口
    Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
    // 服务实现类对应的bean的名字,比如:demoServiceImpl
    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

    // 生成一个ServiceBean
    AbstractBeanDefinition serviceBeanDefinition =
        buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

    // ServiceBean Bean的name   ServiceBean表示服务,我们要使用一个服务应该拿ServiceBean
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

    if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        // 把ServiceBean注册进去,对应的beanName为ServiceBean:org.apache.dubbo.demo.DemoService
        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

表示⼀个Dubbo服务,它有⼀些参数,比如:
  1. ref,表示服务的具体实现类。

  2. interface,表示服务的接口。

  3. parameters,表示服务的参数(@Service注解中所配置的信息)。

  4. application,表示服务所属的应用。

  5. protocols,表示服务所使⽤的协议。

  6. registries,表示服务所要注册的注册中心。

ServiceBean会去关联对应普通的那个Bean对象。并且需要注意的是,ServiceBean实现了ApplicationListener接口,所以当Spring启动完成后会触发onApplicationEvent()⽅法的调用,⽽在这个⽅法内会调⽤export(),这个方法就是服务导出的入口方法。
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    // 当前服务没有被导出并且没有卸载,才导出服务
    if (!isExported() && !isUnexported()) {
        if (logger.isInfoEnabled()) {
            logger.info("The service ready on spring started. service: " + getInterface());
        }
        // 服务导出(服务注册)
        export();
    }
}

1.3、ReferenceAnnotationBeanPostProcess

234234.png

该类继承了AnnotationInjectedBeanPostProcessor.class,且继承的这个类继承了Spring的InstantiationAwareBeanPostProcessorAdapter.class
Spring就会调用AnnotationInjectedBeanPostProcessor类中的postProcessPropertyValues()方法去寻找到注入点。
@Override
public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    // 寻找需要注入的属性(被@Reference标注的Field)
    InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
    try {
        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;
}

private InjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                try {
                    metadata = buildAnnotatedMetadata(clazz);
                    this.injectionMetadataCache.put(cacheKey, metadata);
                } catch (NoClassDefFoundError err) {
                    throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
                                                    "] for annotation metadata: could not find class that it depends on", err);
                }
            }
        }
    }
    return metadata;
}

private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
    // 哪些Filed上有@Reference注解
    Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
    // 哪些方法上有@Reference注解
    Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
    // 返回的是Dubbo定义的AnnotatedInjectionMetadata,接下来就会使用这个类去进行属性注入
    return new AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
}

AnnotatedInjectionMetadata类 (当前类的注入点集合对象)

private class AnnotatedInjectionMetadata extends InjectionMetadata {
    //属性注入点
    private final Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements;
	//方法注入点
    private final Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements;

    public AnnotatedInjectionMetadata(Class<?> targetClass, Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements,
                                      Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements) {
        super(targetClass, combine(fieldElements, methodElements));
        this.fieldElements = fieldElements;
        this.methodElements = methodElements;
    }

    public Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> getFieldElements() {
        return fieldElements;
    }

    public Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> getMethodElements() {
        return methodElements;
    }
}

AnnotatedInjectionMetadata类继承与Spring的InjectionMetadata类,会调用父类的inject()方法去循环调用AnnotatedFieldElement或者AnnotatedMethodElement的inject()方法去对注入点进行注入。

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    // set方法对应的属性的类型
    Class<?> injectedType = pd.getPropertyType();
    // 从Spring容器中获取一个Bean(注意,这个方法内部会生成Bean而且会缓存,就像Spring中的getBean一样)
    Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
    ReflectionUtils.makeAccessible(method);
    // 调用set方法
    method.invoke(bean, injectedObject);

}

protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {
    // 缓存中去拿
    String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);

    Object injectedObject = injectedObjectsCache.get(cacheKey);

    if (injectedObject == null) {
        // 生成Bean
        injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);

        // 放入缓存
        injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
    }
    return injectedObject;
}

上面的getInjectedObject()方法就会调用到ReferenceAnnotationBeanPostProcess的doGetInjectedBean()方法,负责生成对象。

// 该方法得到的对象会赋值给@ReferenceBean注解的属性
@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {

    /**
         * The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
         */
    // 得到引入服务的beanName
    // attributes里存的是@Reference注解中的所配置的属性与值
    // injectedType表示引入的是哪个服务接口
    // referencedBeanName的值为  ServiceBean:org.apache.dubbo.demo.DemoService  表示得到该服务Bean的beanName
    // referencedBeanName表示 我现在要引用的这个服务,它导出时对应的ServiceBean的beanName是什么,可以用来判断现在我引用的这个服务是不是我自己导出的
    String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

    /**
         * The name of bean that is declared by {@link Reference @Reference} annotation injection
         */
    // @Reference(methods=[Lorg.apache.dubbo.config.annotation.Method;@39b43d60) org.apache.dubbo.demo.DemoService
    // 我要生成一个RefrenceBean对应的beanName, 根据@Reference注解来标识不同,有可能版本号不同, 所以要区别开来
    String referenceBeanName = getReferenceBeanName(attributes, injectedType);

    // 生成一个ReferenceBean对象,并放入缓存
    ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

    // 把referenceBean添加到Spring容器中去
    registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);

    cacheInjectedReferenceBean(referenceBean, injectedElement);

    // 创建一个代理对象,Service中的属性被注入的就是这个代理对象
    // 内部会调用referenceBean.get();
    return getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType);
}

private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes,
                                                     Class<?> referencedType)
    throws Exception {
    //判断缓存是否已经有了
    ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);

    if (referenceBean == null) {
        // 生成了一个ReferenceBean对象,attributes是@Reference注解的参数值
        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,
                                       Class<?> interfaceClass) {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    // @Reference(parameters=[Ljava.lang.String;@72ef8d15) org.apache.dubbo.demo.DemoService
    // ReferenceBean的beanName,注意这个beanName,它是直接取的@Reference的全信息
    // 所以,就算引用的是同一个服务,如果@Reference注解上的信息不同,那么就会生成不同的ReferenceBean
    String beanName = getReferenceBeanName(attributes, interfaceClass);

    // 要引入的服务就是本地提供的一个服务
    if (existsServiceBean(referencedBeanName)) { // If @Service bean is local one
        /**
             * Get  the @Service's BeanDefinition from {@link BeanFactory}
             * Refer to {@link ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition}
             */
        AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
        RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref"); // ServiceBean --- ref
        // The name of bean annotated @Service
        String serviceBeanName = runtimeBeanReference.getBeanName();
        // register Alias rather than a new bean name, in order to reduce duplicated beans
        // 如果是本地提供的一个服务,那么就@Reference(parameters=[Ljava.lang.String;@72ef8d15) org.apache.dubbo.demo.DemoService
        // 的别名是demoService,不需要是ServiceBean的名字
        beanFactory.registerAlias(serviceBeanName, beanName);
    } else { // Remote @Service Bean
        // 没有就把referenceBean注册到Spring容器中,方便使用@Autowired获取
        if (!beanFactory.containsBean(beanName)) {
            beanFactory.registerSingleton(beanName, referenceBean);
        }
    }
}

private String getReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
    // id attribute appears since 2.7.3
    String beanName = getAttribute(attributes, "id");

    // beanName为null时会进入if判断
    if (!hasText(beanName)) {
        beanName = generateReferenceBeanName(attributes, interfaceClass);
    }
    return beanName;
}

private String generateReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
    StringBuilder beanNameBuilder = new StringBuilder("@Reference");
    if (!attributes.isEmpty()) {
        beanNameBuilder.append('(');
        for (Map.Entry<String, Object> entry : attributes.entrySet()) {
            beanNameBuilder.append(entry.getKey())
                .append('=')
                .append(entry.getValue())
                .append(',');
        }
        // replace the latest "," to be ")"
        beanNameBuilder.setCharAt(beanNameBuilder.lastIndexOf(","), ')');
    }
    beanNameBuilder.append(" ").append(interfaceClass.getName());
    return beanNameBuilder.toString();
}

private Object getOrCreateProxy(String referencedBeanName, String referenceBeanName, ReferenceBean referenceBean, Class<?> serviceInterfaceType) {
    //看是否能本地获取服务的代理对象
    if (existsServiceBean(referencedBeanName)) { // If the local @Service Bean exists, build a proxy of ReferenceBean
        return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
                                wrapInvocationHandler(referenceBeanName, referenceBean));
    } else {                                    // ReferenceBean should be initialized and get immediately
        // 本地如果没有这个服务就会调用get()去生成代理对象
        return referenceBean.get();
    }
}
为对于Dubbo来说,注⼊给某个属性的应该是当前这个属性所对应的服务接⼝的代理对象。但是在⽣成这个代理对象之前,还要考虑问题:
  1. 当前所需要引⼊的这个服务,是不是在本地就存在?不存在则要把按Dubbo的逻辑⽣成⼀个代理对象。

  2. 当前所需要引⼊的这个服务,是不是已经被引⼊过了(是不是已经⽣成过代理对象了),如果是应该是不⽤再重复去⽣成了。

对于服务引⼊,也应该提前根据@Reference注解中的信息和属性接⼝类型去判断⼀下当前Spring容器中是否存在对应的ServiceBean对象,如果存在则直接取出ServiceBean对象的ref属性所对应的对象,作为要注⼊的结果。

如何判断当前所引⼊的这个服务是否已经被引⼊过了(是不是已经⽣成过代理对象了)?

这就需要在第⼀次引⼊某个服务后(⽣成代理对象后)进⾏缓存(记录⼀下)。Dubbo中是这么做的:
  1. ⾸先根据@Reference注解的所有信息+属性接⼝类型⽣成⼀个字符串。

  2. 然后@Reference注解的所有信息+属性接⼝类型⽣成⼀个ReferenceBean对象(ReferenceBean对象中的get⽅法可以得到⼀个Dubbo⽣成的代理对象,可以理解为服务引⼊的⼊⼝⽅法)。

  3. 把字符串作为beanName,ReferenceBean对象作为bean注册到Spring容器中,同时也会放⼊referenceBeanCache中。

@Reference注解服务引⼊的过程是这样的:

  1. 得到当前所引⼊服务对应的ServiceBean的beanName(源码中叫referencedBeanName)。

  2. 根据@Reference注解的所有信息+属性接⼝类型得到⼀个referenceBeanName。

  3. 根据referenceBeanName从referenceBeanCache获取对应的ReferenceBean,如果没有则创建⼀个ReferenceBean。

  4. 根据referencedBeanName(ServiceBean的beanName)判断Spring容器中是否存在该bean,如果存在则给ref属性所对应的bean取⼀个别名,别名为referenceBeanName。

    1. 如果Spring容器中不存在referencedBeanName对应的bean,则判断容器中是否存在referenceBeanName所对应的Bean,如果不存在则将创建出来的ReferenceBean注册到Spring容器中(此处这么做就⽀持了可以通过@Autowired注解也可以使⽤服务了,ReferenceBean是⼀个FactoryBean)。

  5. 如果referencedBeanName存在对应的Bean,则额外⽣成⼀个代理对象,代理对象的InvocationHandler会缓存在localReferenceBeanInvocationHandlerCache中,这样如果引⼊的是同⼀个服务,并且这个服务在本地。

  6. 如果referencedBeanName不存在对应的Bean,则直接调⽤ReferenceBean的get()⽅法得到⼀个代理对象。


版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

上一篇:2、Dubbo SPI 下一篇:分布式面试

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门