前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊dubbo的DubboComponentScanRegistrar

聊聊dubbo的DubboComponentScanRegistrar

原创
作者头像
code4it
修改2019-08-28 10:27:49
6140
修改2019-08-28 10:27:49
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下dubbo的DubboComponentScanRegistrar

DubboComponentScanRegistrar

dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java

代码语言:javascript
复制
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
​
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
​
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
​
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
​
        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) {
​
        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
        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
        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;
    }
​
}
  • DubboComponentScanRegistrar实现了ImportBeanDefinitionRegistrar接口定义的registerBeanDefinitions方法;它首先通过getPackagesToScan方法从AnnotationMetadata读取要扫描的包,然后再执行registerServiceAnnotationBeanPostProcessor、registerReferenceAnnotationBeanPostProcessor方法
  • getPackagesToScan方法读取DubboComponentScan注解信息,获取要扫描的包;registerServiceAnnotationBeanPostProcessor方法则是通过BeanDefinitionReaderUtils.registerWithGeneratedName注册ServiceAnnotationBeanPostProcessor
  • registerReferenceAnnotationBeanPostProcessor方法则是通过BeanRegistrar.registerInfrastructureBean注册ReferenceAnnotationBeanPostProcessor

DubboComponentScanRegistrarTest

dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java

代码语言:javascript
复制
public class DubboComponentScanRegistrarTest {
​
    @BeforeEach
    public void setUp() {
        ConfigManager.getInstance().clear();
    }
​
    @AfterEach
    public void tearDown() {
        ConfigManager.getInstance().clear();
    }
​
    @Test
    public void test() {
​
        AnnotationConfigApplicationContext providerContext = new AnnotationConfigApplicationContext();
​
        providerContext.register(ProviderConfiguration.class);
​
        providerContext.refresh();
​
        DemoService demoService = providerContext.getBean(DemoService.class);
​
        String value = demoService.sayName("Mercy");
​
        Assertions.assertEquals("Hello,Mercy", value);
​
        Class<?> beanClass = AopUtils.getTargetClass(demoService);
​
        // DemoServiceImpl with @Transactional
        Assertions.assertEquals(DemoServiceImpl.class, beanClass);
​
        // Test @Transactional is present or not
        Assertions.assertNotNull(findAnnotation(beanClass, Transactional.class));
​
        AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
​
        consumerContext.register(ConsumerConfiguration.class);
​
        consumerContext.refresh();
​
        ConsumerConfiguration consumerConfiguration = consumerContext.getBean(ConsumerConfiguration.class);
​
        demoService = consumerConfiguration.getDemoService();
​
        value = demoService.sayName("Mercy");
​
        Assertions.assertEquals("Hello,Mercy", value);
​
        ConsumerConfiguration.Child child = consumerContext.getBean(ConsumerConfiguration.Child.class);
​
        // From Child
​
        demoService = child.getDemoServiceFromChild();
​
        Assertions.assertNotNull(demoService);
​
        value = demoService.sayName("Mercy");
​
        Assertions.assertEquals("Hello,Mercy", value);
​
        // From Parent
​
        demoService = child.getDemoServiceFromParent();
​
        Assertions.assertNotNull(demoService);
​
        value = demoService.sayName("Mercy");
​
        Assertions.assertEquals("Hello,Mercy", value);
​
        // From Ancestor
​
        demoService = child.getDemoServiceFromAncestor();
​
        Assertions.assertNotNull(demoService);
​
        value = demoService.sayName("Mercy");
​
        Assertions.assertEquals("Hello,Mercy", value);
​
        providerContext.close();
        consumerContext.close();
​
​
    }
​
​
}
  • DubboComponentScanRegistrarTest分别验证了providerContext、consumerContext

小结

  • DubboComponentScanRegistrar实现了ImportBeanDefinitionRegistrar接口定义的registerBeanDefinitions方法;它首先通过getPackagesToScan方法从AnnotationMetadata读取要扫描的包,然后再执行registerServiceAnnotationBeanPostProcessor、registerReferenceAnnotationBeanPostProcessor方法
  • getPackagesToScan方法读取DubboComponentScan注解信息,获取要扫描的包;registerServiceAnnotationBeanPostProcessor方法则是通过BeanDefinitionReaderUtils.registerWithGeneratedName注册ServiceAnnotationBeanPostProcessor
  • registerReferenceAnnotationBeanPostProcessor方法则是通过BeanRegistrar.registerInfrastructureBean注册ReferenceAnnotationBeanPostProcessor

doc

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DubboComponentScanRegistrar
  • DubboComponentScanRegistrarTest
  • 小结
  • doc
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档