order
This article focuses on dubbo's dubbo Component Scan Registrar.
DubboComponentScanRegistrar
dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
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 implements the registerBean Definitions method defined by the ImportBean Definition Registrar interface; it first reads the package to be scanned from Annotation Metadata through the getPackagesToScan method, and then executes the registerService Annotation BeanPostProcessor, registerReference Annotation BeanPostProcessor methods.
- The getPackagesToScan method reads DubboComponentScan annotation information to get the package to scan; the registerService Annotation BeanPostProcessor method registers Service Annotation BeanPostProcessor through BeanDefinitionReaderUtils.registerWithGeneratedName
- The registerReference Annotation BeanPostProcessor method registers the Reference Annotation BeanPostProcessor through the BeanRegistrar. registerInfrastructure Bean
DubboComponentScanRegistrarTest
dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
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(); } }
- DubboComponentScan Registrar Test validates providerContext and consumerContext, respectively.
Summary
- DubboComponentScanRegistrar implements the registerBean Definitions method defined by the ImportBean Definition Registrar interface; it first reads the package to be scanned from Annotation Metadata through the getPackagesToScan method, and then executes the registerService Annotation BeanPostProcessor, registerReference Annotation BeanPostProcessor methods.
- The getPackagesToScan method reads DubboComponentScan annotation information to get the package to scan; the registerService Annotation BeanPostProcessor method registers Service Annotation BeanPostProcessor through BeanDefinitionReaderUtils.registerWithGeneratedName
- The registerReference Annotation BeanPostProcessor method registers the Reference Annotation BeanPostProcessor through the BeanRegistrar. registerInfrastructure Bean