Dubbo之旅--啟動解析


 

        通過之前系列文章我們已經對Dubbo已經有了一個整體的印象,接下來我們從其他角度來進一步了解它.Dubbo通過Spring的加載而啟動,本文分析了通過注解方式加載的過程.

 

   1.Schema擴展

 

       通過注解加載dubbo,需要在spring的配置文件中添加:

 

<dubbo:annotationpackage="com.package.to.be.scanned" />

 

dubbo:annotation是dubbo基於spring的schema擴展。

dubbo的schema描述文件在dubbo-config-spring模塊下。我們可以看到在其中定義的xml描述信息。

 

       Spring會默認加載spring.handlers和spring.schemas,從而感知schema描述文檔。從中我們可以看到schema的處理器:com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

 

     DubboNamespaceHandler繼承了NamespaceHandlerSupport。因此不需要實現所有的解析工作,只要將自定義schema中的元素解析器注冊進來就可以。

 

 

public void init() { 

       registerBeanDefinitionParser("application", newDubboBeanDefinitionParser(ApplicationConfig.class, true)); 

       registerBeanDefinitionParser("module", newDubboBeanDefinitionParser(ModuleConfig.class, true)); 

       registerBeanDefinitionParser("registry", newDubboBeanDefinitionParser(RegistryConfig.class, true)); 

       registerBeanDefinitionParser("monitor", newDubboBeanDefinitionParser(MonitorConfig.class, true)); 

       registerBeanDefinitionParser("provider", newDubboBeanDefinitionParser(ProviderConfig.class, true)); 

       registerBeanDefinitionParser("consumer", newDubboBeanDefinitionParser(ConsumerConfig.class, true)); 

       registerBeanDefinitionParser("protocol", newDubboBeanDefinitionParser(ProtocolConfig.class, true)); 

       registerBeanDefinitionParser("service", newDubboBeanDefinitionParser(ServiceBean.class, true)); 

       registerBeanDefinitionParser("reference", newDubboBeanDefinitionParser(ReferenceBean.class, false)); 

       registerBeanDefinitionParser("annotation", newDubboBeanDefinitionParser(AnnotationBean.class, true)); 

 

       在代碼中我們可以看到被注冊的annotation解析器:DubboBeanDefinitionParser。Parser中的privatestaticBeanDefinition parse()方法實現了解析,並返回解析后生成bean的定義。接下來我們就看一下dubbodubbo:annotation的加載過程。

 

 

 

   2. Dubbo 自定義元素加載

 

      Spring啟動后,加載配置文件信息,得到dubbo的schema元素定義信息:<dubbo:annotation package="com.package.to.be.scanned" />

 

        根據DubboNamespaceHandler中注冊的信息,spring找到解析類並調用解析方法:DubboBeanDefinitionParser.Parse()。

 

第一步,初始化RootBeanDefinition

 

第二步,獲取beanid

 

第三步,將xml中配置的信息放到beandefinition的PropertyValues中。

 

最后返回AnnotationBean的BeanDefinition。

 

至此,annotation對應的bean定義解析完畢,spring知曉了AnnotationBean的存在。

 

 

 

   3.  AnnotationBean運行

 

      AnnotationBean實現了很多spring的特殊bean接口:DisposableBean,BeanFactoryPostProcessor,BeanPostProcessor,ApplicationContextAware。這保證AnnotationBean能夠在spring加載的各個時期實現自己的功能。

 

      注解掃描的功能在beanfactory初始化完成調用接口BeanFactoryPostProcessor.postProcessBeanFactory中實現。

 

實現代碼:

 

public voidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 

            throws BeansException { 

        if (annotationPackage == null ||annotationPackage.length() == 0) { 

            return; 

        } 

        if (beanFactory instanceofBeanDefinitionRegistry) { 

            try { 

                // init scanner 

                Class<?> scannerClass =ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner"); 

                Object scanner =scannerClass.getConstructor(new Class<?>[] {BeanDefinitionRegistry.class,boolean.class}).newInstance(new Object[] {(BeanDefinitionRegistry) beanFactory,true}); 

                // add filter 

                Class<?> filterClass =ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); 

                Object filter =filterClass.getConstructor(Class.class).newInstance(Service.class); 

                Method addIncludeFilter =scannerClass.getMethod("addIncludeFilter",ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")); 

               addIncludeFilter.invoke(scanner, filter); 

                // scan packages 

                String[] packages =Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); 

                Method scan =scannerClass.getMethod("scan", newClass<?>[]{String[].class}); 

                scan.invoke(scanner, newObject[] {packages}); 

            } catch (Throwable e) { 

                // spring 2.0 

            } 

        } 

 

           AnnotationBean的參數annotationPackage,就是在beandefinition創建時,從xml中讀取到spring中。源碼通過ClassPathBeanDefinitionScanner.doScan掃描annotationPackage下所有的文件。配置成bean的類會定義成BeanDefinition,注冊到spring。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com