序
本文主要研究一下dubbo的DubboComponentScanRegistrar
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实现了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
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。