dubbo annocation scan启动过程解析

Dubbo通过spring的加载而启动,本文分析了通过注解方式加载的过程.

1.      Schema扩展

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

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

dubbo:annotation是dubbo基于spring的schema扩展。(Schema扩展的介绍可以参考:http://blog.csdn.net/cutesource/article/details/5864562。详细信息参考w3cshool)

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", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.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 DubboBeanDefinitionParser(AnnotationBean.class, true));
}

在代码中我们可以看到被注册的annotation解析器:DubboBeanDefinitionParserParser中的privatestatic BeanDefinition parse()方法实现了解析,并返回解析后生成bean的定义。接下来我们就看一下dubbo dubbo: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 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        if (annotationPackage == null || annotationPackage.length() == 0) {
            return;
        }
        if (beanFactory instanceof BeanDefinitionRegistry) {
            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", new Class<?>[]{String[].class});
                scan.invoke(scanner, new Object[] {packages});
            } catch (Throwable e) {
                // spring 2.0
            }
        }
}

AnnotationBean的参数annotationPackage,就是在beandefinition创建时,从xml中读取到spring中。源码通过ClassPathBeanDefinitionScanner. doScan扫描annotationPackage下所有的文件。配置成bean的类会定义成BeanDefinition,注册到spring。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值