dubbo学习篇2 注解之 @Service 原理解析

一.使用注解

在dubbo springboot 使用时,在需要调用的服务接口上使用 @Service 即可将接口实现作为服务暴露 即可给消费者调用

@Service(version = "1.0.0",
        application = "${dubbo.application.id}",
        protocol = "${dubbo.protocol.id}",
        registry = "${dubbo.registry.id}")
@Slf4j
public class HelloServiceImpl implements HelloService {

dubbo 如何在 spring 中完成了服务注册发布 本文记录了调试跟踪过程

二.原理分析

1.学习篇一中对ReferenceAnnotationBeanPostProcessor有了详细跟踪,在同一目录 还有ServiceAnnotationBeanPostProcessor

此类实现了@Service 注解的解析 不过此流程相对简单 篇幅相对会较短

2.与ReferenceAnnotationBeanPostProcessor不同 ServiceAnnotationBeanPostProcessor 实现 BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor分别实现其中的postProcessBeanDefinitionRegistry (添加),postProcessBeanFactory(修改)方法 .

3.spring 通过该接口提供了一种机制 使得扩展方可以动态的添加和修改bean的定义 他们在其他bean初始化完毕后首先调用postProcessBeanDefinitionRegistry 等所有BeanDefinitionRegistryPostProcessor调用完毕后 按顺序调postProcessBeanFactory来修改部分bean.

 

三.源码分析

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        Set<String> resolvedPackagesToScan = this.resolvePackagesToScan(this.packagesToScan);
        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            this.registerServiceBeans(resolvedPackagesToScan, registry);
        } else if (this.logger.isWarnEnabled()) {
            this.logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }

    }

重点是这个函数 获取到需要扫描的包 然后扫描其中带有@Service的定义 然后将扫描到的定义加入到beanfactory的beandefinitionmap中

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
        DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, this.environment, this.resourceLoader);
        BeanNameGenerator beanNameGenerator = this.resolveBeanNameGenerator(registry);
        scanner.setBeanNameGenerator(beanNameGenerator);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
        Iterator i$ = packagesToScan.iterator();

        while(true) {
            while(i$.hasNext()) {
                String packageToScan = (String)i$.next();
                scanner.scan(new String[]{packageToScan});
                Set<BeanDefinitionHolder> beanDefinitionHolders = this.findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
                if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
                    Iterator i$ = beanDefinitionHolders.iterator();

                    while(i$.hasNext()) {
                        BeanDefinitionHolder beanDefinitionHolder = (BeanDefinitionHolder)i$.next();
                        this.registerServiceBean(beanDefinitionHolder, registry, scanner);
                    }

                    
                } 
            }

            return;
        }
    }

 

上述函数主要递归扫描package 然后添加到系统定义 相对比较简单。

 

不过到此有个疑问 那么是何时如何执行发布的呢? 网上搜索加上查看调用堆栈发现发布的源头在ServiceBean 的事件响应函数中

 

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware 

public void onApplicationEvent(ContextRefreshedEvent event) {
        if (this.isDelay() && !this.isExported() && !this.isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + this.getInterface());
            }

            this.export();
        }

    }

可以看出ServiceBean通过注册 onfresh结束事件在spring完成刷新后开始执行服务的暴露。

另外 ServiceBean会在spring在为每个注册的单例bean 初始化时构造。

至此基本搞清楚dubbo依赖 

@Service @Reference 两个注解完成服务注册和调用的spring 解析过程 下篇开始分析dubbo本身服务发布和调用的过程

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值