IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Dubbo学习记录(五)-Dubbo与Spring的配置文件解析流程原理分析 -> 正文阅读

[Java知识库]Dubbo学习记录(五)-Dubbo与Spring的配置文件解析流程原理分析

Dubbo与Spring的整合原理与流程分析

看Dubbo整合Spring的使用, 几个注解就结束了,但是内部运作原理一概不知, 框架内部报错,丢出异常都不知道是怎么回事, 最终还是决定花点时间看看dubbo的一些流程源码。

主要内容

看看Dubbo与Spring是如何做到无缝结合, 以及注解类是怎么被加载的。

  1. Dubbo中propertie?件解析以及处理流程原理
  2. Dubbo中@Service注解解析以及处理流程原理
  3. Dubbo中@Reference注解解析以及处理流程原理

启动类

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

两个关键的注解:

  • @EnableDubbo注解:指定我们dubbo服务类的包路径, 这些服务类是使用Dubbo服务的@Service注解修饰的服务类;
  • @PropertySource注解: 用来指定我们Dubbo配置文件的路径, 然后通过@Value注解使用配置文件的内容,类似SpringBoot的application.properties文件一样被加载;

1. @EnableDubbo注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
	//省略一些方法
}

该注解上面有两个关键的注解:

  1. EnableDubboConfig
    读取properties配置文件, 并将配置转换成一个个的配置Bean;
  2. DubboComponentScan
    扫描服务提供者和引用者类(即使用@Service修饰的类)

2. @EnableDubboConfig与@DubboComponentScan

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

}

通过@Import注解,引入DubboConfigConfigurationRegistrar类, 将这个类转换一个Bean注入容器, 另外, 还会使用这个类将所有的配置转换成Bean注入容器;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
    String[] value() default {};
    String[] basePackages() default {};
    Class<?>[] basePackageClasses() default {};

}

通过@Import注解,引入DubboComponentScanRegistrar类, 将这个类转换一个Bean注入容器, 另外, 还会使用这个类扫描所有的服务提供类,转换成ServiceBean注入容器;

3. DubboConfigConfigurationRegistrar

  • 扫描配置类
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    //

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
       //...省略部分代码

        //获取EnableDubboConfig的属性值,有一个multiple
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        //获取multiple属性的值
        boolean multiple = attributes.getBoolean("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);
        }
    }
}
  1. 获取EnableDubboConfig的所有属性值;
  2. 获取EnableDubboConfig的Multiple值;
  3. 注册单例绑定Bean;
  4. 注册多例绑定Bean;

当Spring启动后, 肯定会通过AnnotationBeanDefinitionReader来执行registerBeanDefinitions方法的。(看了挺多博客, 都是这么说, Spring源码没了解那么深);

3.1 DubboConfigConfiguration.Single类

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

    }

Single类 通过 @EnableDubboConfigBinding注解可以看出,根据Dubbo的配置前缀进行Bean类型的绑定, 例如dubbo.application配置, 对应的类型是一个ApplicationConfig类的Bean;

3.2 DubboConfigConfiguration.Multiple

    /**
     * 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 {

    }
  • Multiple类 通过 @EnableDubboConfigBinding注解可以看出,根据Dubbo的配置前缀进行Bean类型的绑定, 例如dubbo.protocols配置多个协议, 而且每种协议都会转换成一个类型为ProtocolConfig类的Bean。

  • 下面的例子,我就理解了:

#dubbo.protocol.name=dubbo
#dubbo.protocol.port=20881
#dubbo.protocol.host=0.0.0.0

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.protocol.: 会生成单个Bean, Bean的类型是ProtocolConfig
  • dubbo.protocols: 会生成多个Bean, Bean的类型是ProtocolConfig, Bean的名称与p1, p2有关

3.3 @EnableDubboConfigBindings注解

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

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

}

  • value值是一个EnableDubboConfigBinding数组
  • 通过@Import注解,导入DubboConfigBindingsRegistrar.class类, 该类会获取@EnableDubboConfigBindings注解中的value,也就是多个@EnableDubboConfigBinding注解,然后利用DubboConfigBindingRegistrar去处理这些@EnableDubboConfigBinding注解。

DubboConfigBindingsRegistrar

  • Spring启动时, AnnotationBeanDefinitionReader来执行registerBeanDefinitions方法;
public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private ConfigurableEnvironment environment;

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

        // 拿到多个@EnableDubboConfigBinding注解
        AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");

        DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar();
        registrar.setEnvironment(environment);

        for (AnnotationAttributes element : annotationAttributes) {

            // 逐个解析@EnableDubboConfigBinding注解,比如@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class)
            registrar.registerBeanDefinitions(element, registry);

        }
    }
	//省略无关代码;
}
  1. 获取EnableDubboConfigBindings所有的属性值
  2. 获取EnableDubboConfigBindings的value属性值;
  3. 创建配置绑定注册Bean工具类对象, 用来注册一个个的配置Bean
  4. 遍历循环, 逐个解析@EnableDubboConfigBinding注解类;第一个参数事注解类信息,第二个参数是Spring容器,方便将Bean注入容器;
DubboConfigBindingRegistrar

解析@EnableDubboConfigBinding注解类

public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

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

    private ConfigurableEnvironment environment;

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

    }
}

作用:

  1. 获取绑定注解prefix属性, 即配置的属性dubbo.application
  2. 获取绑定注解type属性, 是每一中配置对应的类型Class信息;
  3. 获取绑定注解multiple属性
  4. 根据prefix, type, multipart生成Bean注入容器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后置处理器
            registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry);

        }

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

    }

工作:

  1. getSubProperties:获取propertis信息中,包含了绑定注解前缀prefix的配置
  2. resolveMultipleBeanNames | resolveSingleBeanName: 生成注入容器的Bean的名称;
  3. 遍历生成的Bean名称;
    3.1 registerDubboConfigBean为每个Bean名称注入一个空的BeanDefinition对象
    3.2 registerDubboConfigBindingBeanPostProcessor为每个Bean注册一个DubboConfigBindingBeanPostProcessor后置处理器;
  4. registerDubboConfigBeanCustomizers:注册一个NamePropertyDefaultValueDubboConfigBeanCustomizer的bean
  • getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix)
	//主要:1. propertySources转化转换为AbstractEnvironment 对象
    public static Map<String, Object> getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix) {
        // Non-Extension AbstractEnvironment
        AbstractEnvironment environment = new AbstractEnvironment() {
        };
        MutablePropertySources mutablePropertySources = environment.getPropertySources();
        for (PropertySource<?> source : propertySources) {
            mutablePropertySources.addLast(source);
        }
        return getSubProperties(environment, prefix);
    }
    //1. 获取所有环境配置
    //2. normalizePrefix生成绑定 前缀字符串 prefix+"." , 多了一个点;
    //3. 遍历循环所有配置
    //3.1 找到所有前缀字符串开头的 配置项
    //3.2 name.substring(normalizedPrefix.length())截取字符串, 前缀字符串后面的内容全部截取下来;
    //3.3 获取前缀字符串配置项对应的值;
    //3.4 subProperties.put(subName, value)将结果放入容器中subProperties 
    public static Map<String, Object> getSubProperties(ConfigurableEnvironment environment, String prefix) {

        Map<String, Object> subProperties = new LinkedHashMap<>();

        MutablePropertySources propertySources = environment.getPropertySources();

        String normalizedPrefix = normalizePrefix(prefix);

        for (PropertySource<?> source : propertySources) {
            if (source instanceof EnumerablePropertySource) {
                for (String name : ((EnumerablePropertySource<?>) source).getPropertyNames()) {
                    if (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) {
                        String subName = name.substring(normalizedPrefix.length());
                        if (!subProperties.containsKey(subName)) { // take first one
                            Object value = source.getProperty(name);
                            if (value instanceof String) {
                                // Resolve placeholder
                                value = environment.resolvePlaceholders((String) value);
                            }
                            subProperties.put(subName, value);
                        }
                    }
                }
            }
        }

        return Collections.unmodifiableMap(subProperties);

    }
    
    
  • resolveMultipleBeanNames(properties)
    获取Multiple下的bean名称;
	//1. 创建一个Set集合, 作用是用来去重
	//2. 遍历前缀对应的所有配置项的Key;
	//3. 获取"."号出现的问题的位置;
	//4. 将Bean的名称放入Set集合。相同就去重;
    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;
    }
  • resolveSingleBeanName(properties, configClass, registry)
    获取single配置的Bean名称;
	//1. 获取id的值;
	//2. id值为空,自动生成一个Bean的名称;
	//3. Id值不为空,就用来当作bean的名称,返回;
    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;

    }

  • registerDubboConfigBean(beanName, configClass, registry)
    创建一个空的BeanDefinition类,并放入IOC容器
	//1. 创建BeanDefinitionBuilder构造类实例;
	//2. 获取一个BeanDefinition类的实例;
	//3. 根据已经生成bean名称,空的BeanDefinition实例, 注入IOC容器中;
    private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,
                                         BeanDefinitionRegistry registry) {

        BeanDefinitionBuilder builder = rootBeanDefinition(configClass);

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

        registry.registerBeanDefinition(beanName, beanDefinition);   // ApplicatinoConfig对象

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

    }
  • registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry)
    创建一个DubboConfigBindingBeanPostProcessor后置处理器, 并注入容器;
	//1. 创建DubboConfigBindingBeanPostProcessor的一个BeanDefinitionBuilder构建对象;
	//2. 获取真实前缀, 如果Multiple为true, 则是dubbo.protocols.p1, 为false, 则是dubbo.protocol;
	//3. 添加两个构造方法参数;
	//4. 创建一个空的DubboConfigBindingBeanPostProcessor的BeanDefinition对象;
	//5. 生成DubboConfigBindingBeanPostProcessor的bean名称为key, 空BeanDefinition实例注入容器;
    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.");
        }

    }
    
    public static String registerWithGeneratedName(AbstractBeanDefinition definition, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String generatedName = generateBeanName(definition, registry, false);
        registry.registerBeanDefinition(generatedName, definition);
        return generatedName;
    }
    //
    public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException {
        //获取BeanDefinition 的 beanName;
        String generatedBeanName = definition.getBeanClassName();
		//...省略部分代码
        if (!StringUtils.hasText(generatedBeanName)) {
   		//异常处理
        } else {
            String id = generatedBeanName;
            if (isInnerBean) {
                id = generatedBeanName + "#" + ObjectUtils.getIdentityHexString(definition);
            } else {
            	//判断存在多少id为generatedBeanName, 如果有count自增1, 最后容器不包含
            	//generatedBeanName + "#" + counter的bean名称时,就是用这个组合字符串作为Bean名称;
                for(int counter = -1; counter == -1 || registry.containsBeanDefinition(id); id = generatedBeanName + "#" + counter) {
                    ++counter;
                }
            }

            return id;
        }
    }

3. registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)

注册各个Dubbo配置Bean到容器中;

 
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    //

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

        //获取EnableDubboConfig的属性值,有一个multiple
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        //获取multiple属性的值
        boolean multiple = attributes.getBoolean("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);
        }
    }

}

回到开头的第3步骤;

4. registerBeans(registry, DubboConfigConfiguration.Multiple.class)

Spring中的AnnotatedBeanDefinitionReader来解析annotatedClasses会解析该类上的注解,然后进行处理

	// annotatedClasses 参数值为 :  DubboConfigConfiguration.Single.class,
	// DubboConfigConfiguration.Multiple.class;
	//作用:
	//1. annotatedClasses转换为迭代器;
	//2. 遍历迭代器,判断容器中是否已经存在这个Bean类
	//如果存在就在这个Bean从迭代器中去掉;
	//isPresentBean(registry, annotatedClass)
	//3. 创建一个AnnotatedBeanDefinitionReader对象实例;
	//4. Spring中的AnnotatedBeanDefinitionReader来解析annotatedClasses,
	//会解析该类上的注解,然后进行处理(Spring的内容)
    public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {
        if (ObjectUtils.isEmpty(annotatedClasses)) {
            return;
        }

        // Remove all annotated-classes that have been registered
        Iterator<Class<?>> iterator = new ArrayList<>(asList(annotatedClasses)).iterator();

        while (iterator.hasNext()) {
            Class<?> annotatedClass = iterator.next();
            if (isPresentBean(registry, annotatedClass)) {
                iterator.remove();
            }
        }

        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);

        if (logger.isDebugEnabled()) {
            logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
        }
        // 利用Spring中的AnnotatedBeanDefinitionReader来解析annotatedClasses
        // 会解析该类上的注解,然后进行处理
        reader.register(annotatedClasses);

    }

总结

@EnableDubboConfig注解的作用就是通过DubboConfigConfigurationRegistrar 解析配置文件里面所有的dubbo配置项。

  1. 通过AnnotatedBeanDefinitionReader来解析Multiple/Single类型上的EnableDubboConfigBindings的值(是一个@EnableDubboConfigBinding数组)
  2. 读取配置文件中Dubbo的所有配置项,根据@EnableDubboConfigBinding绑定注解的prefix前缀,匹配配置项的key, 然后将单个配置项,或者一组配置项转换成一个个type类型Class的BeanDefinition的Bean, 注入IOC容器;
  3. 然后每个XxConfig的Bean会生成对应一个DubboConfigBindingBeanPostProcessor的Bean注入IOC容器
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 15:57:54  更:2022-03-03 15:58:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:08:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码