程序员人生 网站导航

Dubbo之旅--启动解析

栏目:框架设计时间:2015-05-06 08:30:00

 

         通过之前系列文章我们已对Dubbo已有了1个整体的印象,接下来我们从其他角度来进1步了解它.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的定义。接下来我们就看1下dubbodubbo:annotation的加载进程。

 

 

 

   2. Dubbo 自定义元素加载

 

       Spring启动后,加载配置文件信息,得到dubbo的schema元素定义信息:<dubbo:annotation package="com.package.to.be.scanned" />

 

        根据DubboNamespaceHandler中注册的信息,spring找到解析类并调用解析方法:DubboBeanDefinitionParser.Parse()。

 

第1步,初始化RootBeanDefinition

 

第2步,获得beanid

 

第3步,将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。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐