ubbo通过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解析器:DubboBeanDefinitionParser。Parser中的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 {
-
- 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});
-
- 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);
-
- 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) {
-
- }
- }
- }
AnnotationBean的参数annotationPackage,就是在beandefinition创建时,从xml中读取到spring中。源码通过ClassPathBeanDefinitionScanner. doScan扫描annotationPackage下所有的文件。配置成bean的类会定义成BeanDefinition,注册到spring。