dubbo源码分析学习---dubbo 服务端服务暴露过程

   今天来就带大家看看 Dubbo 服务暴露过程,这个过程在 Dubbo 中其实是很核心的过程之一,关乎到你的 Provider 如何能被 Consumer 得知并调用。

   今天还是会进行源码解析,毕竟我们需要深入的去了解 Dubbo 是如何做的,只有深入它才能了解它。

  如果要实现服务发布和注册,需要做哪些事情?

  • 1. 配置文件解析或者注解解析
  • 2. 服务注册
  • 3. 启动 netty 服务实现远程监听

一、前奏 URL

不过在进行服务暴露流程分析之前有必要先谈一谈 URL,有人说这 URL 和 Dubbo 啥关系?有关系,有很大的关系!

一般而言我们说的 URL 指的就是统一资源定位符,在网络上一般指代地址,本质上看其实就是一串包含特殊格式的字符串,标准格式如下:

protocol://username:password@host:port/path?key=value&key=value

Dubbo 就是采用 URL 的方式来作为约定的参数类型,被称为公共契约,就是我们都通过 URL 来交互,来交流。

你想一下如果没有一个约束,没有指定一个都公共的契约那么不同的接口就会以不同的参数来传递信息,一会儿用 Map、一会儿用特定分隔的字符串,这就是导致整体很乱,并且解析不能统一。

用了一个统一的契约之后,那么代码就更加的规范化、形成一种统一的格式,所有人对参数就一目了然,不用去揣测一些参数的格式等等。

而且用 URL 作为一个公共约束充分的利用了我们对已有概念的印象,通俗易懂并且容易扩展,我们知道 URL 要加参数只管往后面拼接就完事儿了。

因此 Dubbo 用 URL 作为配置总线,贯穿整个体系,源码中 URL 的身影无处不在。

URL 具体的参数如下:

  • protocol:指的是 dubbo 中的各种协议,如:dubbo thrift http

  • username/password:用户名/密码

  • host/port:主机/端口

  • path:接口的名称

  • parameters:参数键值对

二、配置解析

2.1、Dubbo 对于 sping 的扩展

    最早我们使用 Spring 的配置,来实现 dubbo 服务的发布,方便大家的同时,也意味着 Dubbo 里面和 Spring 肯定有那种说不清的关系。

2.1.1、Spring 的标签扩展

在 spring 中定义了两个接口

NamespaceHandler: 注册一堆 BeanDefinitionParser,利用他们来进行解析

BeanDefinitionParser:用于解析每个 element 的内容。

Spring 默认会加载 jar 包下的 META-INF/spring.handlers 文件寻找对应的 NamespaceHandler。 Dubbo-config 模块下的 dubboconfig-spring\src\main\resources\META-INF\spring.handlers。

2.2、Dubbo 的实现

     Dubbo 中 spring 扩展就是使用 spring 的自定义类型,所以同样也有 NamespaceHandler、BeanDefinitionParser。而 NamespaceHandler 是 DubboNamespaceHandler

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    @Override
    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
        registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

}

    BeanDefinitionParser 全部都使用了 DubboBeanDefinitionParser,如果我们想看 dubbo:service 的配置,就直接看 DubboBeanDefinitionParser(ServiceBean.class,true)。

   这个里面主要做了一件事,把不同的配置分别转化成 spring 容器中的 bean 对象。

  application 对应 ApplicationConfig

  registry 对应 RegistryConfig

  monitor 对应 MonitorConfig

  provider 对应 ProviderConfig

consumer 对应 ConsumerConfig

   我们仔细看,发现涉及到服务发布和服务调用的两个配置的解析,使用的是 ServiceBean 和 referenceBean。并不是 config 结尾 的,这两个类稍微特殊些,当然他同时也继承了 ServiceConfig 和 ReferenceConfig。

registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));

DubboBeanDefinitionParser

这里面是实现具体配置文件解析的入口,它重写了 parse 方法,对 spring 的配置进行解析。我们关注一下 ServiceBean 的解析. 实际就是解析 dubbo:service 这个标签中对应的属性。

 // 解析 dubbo:service 这个标签中对应的属性
        else if (ServiceBean.class.equals(beanClass)) {
            String className = element.getAttribute("class");
            if (className != null && className.length() > 0) {
                //封装BeanDefinition 对象
                RootBeanDefinition classDefinition = new RootBeanDefinition();
                classDefinition.setBeanClass(ReflectUtils.forName(className));
                classDefinition.setLazyInit(false);
                parseProperties(element.getChildNodes(), classDefinition);
                beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
            }
        } 

2.3、ServiceBean 的实现

ServiceBean 这个类,分别实现了 InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware, ApplicationEventPublisherAware

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

InitializingBean

    接口为 bean 提供了初始化方法的方式,它只包括 afterPropertiesSet 方法,凡是继承该接口的类,在初始化 bean 的时候会执行 该方法。被重写的方法为 afterPropertiesSet。

DisposableBean

被重写的方法为 destroy,bean 被销毁的时候,spring 容器会自动执行 destory 方法,比如释放资源。

ApplicationContextAware

实现了这个接口的 bean,当 spring 容器初始化的时候,会自动的将 ApplicationContext 注入进来

ApplicationListener

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值