聊聊dubbo的DubboComponentScanRegistrar
阿新 • • 發佈:2019-12-31
序
本文主要研究一下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,value);
ConsumerConfiguration.Child child = consumerContext.getBean(ConsumerConfiguration.Child.class);
// From Child
demoService = child.getDemoServiceFromChild();
Assertions.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assertions.assertEquals("Hello,value);
// From Parent
demoService = child.getDemoServiceFromParent();
Assertions.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assertions.assertEquals("Hello,value);
// From Ancestor
demoService = child.getDemoServiceFromAncestor();
Assertions.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assertions.assertEquals("Hello,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