dubbo源码学习--消费端启动

原创
2016/03/23 15:30
阅读数 164

    在配置dubbo的时候,采用了<dubbo:registry/><dubbo:application/>等标签,从这里入手开始学习源码。

1:添加自定义schema,spring提供了可扩展性的schema,这里以dubbo:registry为例子说明。

    自定义schema需要以下几个部分:

    a:自定义javabean:RegistryConfig.java

    b:自定义xsd文件:dubbo.xsd

    c:编写NamespaceHandler和BeanDefinitionParser进行解析:DubboBeanDefinitionParser和DubboNamespaceHandler

    d:编写spring.handlers和spring.schemas将自定义的NamespaceHandler和xsd文件结合

    e:在BeanDefinitionParser中进行应用

2:详细学习--标签解析器初始化DubboNamespaceHandler

DubboNamespaceHandler继承了NamespaceHandlerSupport,override了init方法,在spring启动的过程中会执行init方法初始化bean的解析器

//以注册为例,配置<dubbo:registry/>的解析器,将节点registry和解析器DubboBeanDefinitionParser结合起来
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class,
 true));

   查看源码还可以发现static代码块,只要用来检测classpath是否存在重复,深入底层可以看见,默认是false,不检测,也就是说在此处没有作用

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

3:详细学习--标签解析器进行标签解析DubboBeanDefinitionParser

首先看类的定义,DubboBeanDefinitionParser实现了Spring的BeanDefinitionParser接口,该接口时专门 用来解析Bean的定义的(一看类名就应该知道),并且实现了public BeanDefinition parse(Element element, ParserContext parserContext)方法(别看整个方法返回了一个BeanDefinition对象,其实Spring并没有利用整个返回的对象,具体你可以看 看Spring的源码,所以要把Bean的定义注入到Spring容器中,就需要手动的往Spring中注入,因为Spring没有给我们来做这件事 请。),然后调用了静态方法private static BeanDefinition parse(...),那么该类主要就是在静态的方法parse上了。由于该方法内容实在是太长了,不便粘贴出全部内容,我只分析主要的部分。在 DubboBeanDefinitionParser构造方法参数上有一个Class<?> beanClass参数,它就是指定讲当前标签配置内容转换成对应类的BeanDefinition并且注入到Spring容器中。DubboBeanDefinitionParser实现了BeanDefinitionParser接口,<dubbo:registry/>标签时,会执行parse方法

这里dubbo进行了一个简单封装,增加了一个参数required,此时更加灵活(其实主要是因为reference:依赖的时候存有id,需要单独赋值)

  执行完成之后,这个时候spring IOC 已经知晓ReferenceBean的存在

 @SuppressWarnings("unchecked")
    private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);
        .......................
        if (id != null && id.length() > 0) {
            if (parserContext.getRegistry().containsBeanDefinition(id))  {
                throw new IllegalStateException("Duplicate spring bean id " + id);
            }
            parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
             beanDefinition.getPropertyValues().addPropertyValue("id", id);

最主要的是这句话

beanDefinition.getPropertyValues().addPropertyValue

上面代码很显然看到是通过反射的形式获取类的get/set方法然,从而判断该参数是否可以通过Spring注入进去,最后添加到beanDefinition中,并且注入到Spring容器中。上面则是从Spring中加载配置的机制。

4:spring 知晓bean的存在之后,现在开始查看ReferenceBean代码

实现了多个spring FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean

其中spring的生命周期 InitializingBean和DisposableBean

实现InitializingBean保证了执行afterPropertiesSet()方法

ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, 
ApplicationContextAware, InitializingBean, DisposableBean
getConsumer()
getApplication()
getModule()
getRegistries()
getMonitor()
//一系列方法只是为了保证基本参数的初始化正确性
getObject()


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部