Dubbo源码阅读(三)-Dubbo 服务注册

4 篇文章 0 订阅

一、Dubbo服务注册成ServiceBean

通过注解来注册Dubbo服务的时候,在服务端和消费端都需要用到一个组件DubboComponentScanRegistrar,先看下registerBeanDefinitions()方法:

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

	Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
	
	// 服务端服务注册
	registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

	// 消费端服务注册
	registerReferenceAnnotationBeanPostProcessor(registry);

}

DubboComponentScanRegistrar#registerServiceAnnotationBeanPostProcessor

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

    }

我们来看下 ServiceAnnotationBeanPostProcessor的继承关系:
在这里插入图片描述

看到这个继承关系,是不是很容易就联想到之前Mybatis源码分析中的MapperScannerConfigurer,没错确实有异曲同工之妙!
这个后置处理器会执行postProcessBeanDefinitionRegistry()方法,接着执行ServiceAnnotationBeanPostProcessor#registerServiceBeans()

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

	
	// Dubbo会创建自己的扫描器
	DubboClassPathBeanDefinitionScanner scanner =
			new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

	BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

	scanner.setBeanNameGenerator(beanNameGenerator);

	scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));

	/**
	 * Add the compatibility for legacy Dubbo's @Service
	 *
	 * The issue : https://github.com/apache/dubbo/issues/4330
	 * @since 2.7.3
	 */
	scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class));

	for (String packageToScan : packagesToScan) {

		// Registers @Service Bean first
		scanner.scan(packageToScan);

		// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
		Set<BeanDefinitionHolder> beanDefinitionHolders =
				findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

		if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

			for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
				registerServiceBean(beanDefinitionHolder, registry, scanner);
			}

			if (logger.isInfoEnabled()) {
				logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
						beanDefinitionHolders +
						" } were scanned under package[" + packageToScan + "]");
			}

		} else {

			if (logger.isWarnEnabled()) {
				logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
						+ packageToScan + "]");
			}

		}

	}

}

我们就来看下DubboClassPathBeanDefinitionScanner#doScan

public Set<BeanDefinitionHolder> doScan(String... basePackages) {

	// 调用父类ClassPathBeanDefinitionScanner#doScan将被@Service(Dubbo)注解的类注入Spring IOC容器中
	return super.doScan(basePackages);
}

ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition()方法中有个BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);进去看下:

public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, String factoryMethodName) {
	BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
	builder.beanDefinition = new RootBeanDefinition();
	
	// 此处偷梁换柱把服务定义成ServiceBean.class!
	builder.beanDefinition.setBeanClass(beanClass);
	builder.beanDefinition.setFactoryMethodName(factoryMethodName);
	return builder;
}

二 Dubbo服务暴露

上面的服务注册到Spring IOC容器每一个服务其实就是一个ServiceBean,ServiceBean 实现了 ApplicationListener,在 Spring 容器初始化的时候会调用 onApplicationEvent 方法。ServiceBean 重写了 onApplicationEvent 方法,实现了服务暴露的功能。
ServiceBean#onApplicationEvent

public void onApplicationEvent(ContextRefreshedEvent event) {
	if (!isExported() && !isUnexported()) {
		if (logger.isInfoEnabled()) {
			logger.info("The service ready on spring started. service: " + getInterface());
		}
		
		// 暴露服务
		export();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值