dubbo service export过程
来源:互联网 发布:庚子赔款 知乎 编辑:程序博客网 时间:2024/06/01 14:07
1. AnnotationBean注册
AnnotationBean 的注册通过xml配置. Spring通过读取解析xml,而获得AnnotationBean. AnnotationBean实例化了BeanFactoryPostProcessor,所以在BeanFactory初始化后,会调用 AnnotationBean. postProcessBeanFactory. AnnotationBean通过反射,调用ClassPathBeanDefinitionScanner进行Bean扫描.并通过 IncludeFilter机制,让ClassPathBeanDefinitionScanner加载包含Service注解的Bean.
2. Annotation全局扫描
AnnotationBean 将扫描委托给ClassPathBeanDefinitionScanner实现.而AnnotationBean关心的Service注解,也是通过 IncludeFilter添加到ClassPathBeanDefinitionScanner.这里所介绍的内容更加接近于Spring的包扫描机 制.
ClassPathBeanDefinitionScanner.scan(String...basePackages)是包扫描的入口,而真正的实现则在doScan(String... basePackages)中.源码:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();for (int i = 0; i < basePackages.length; i++) {//扫描包下所有的类,过滤出符合条件的类,生成BeanDefinition.Set<BeanDefinition> candidates = findCandidateComponents(basePackages[i]);for (BeanDefinition candidate : candidates) {String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);if (checkCandidate(beanName, candidate)) {//使用BeanDefinitionHolder来装饰bean.BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder = applyScope(definitionHolder, scopeMetadata);beanDefinitions.add(definitionHolder);//将bean注册到beanFactory中registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}
3. Reference 自动注入
AnnotationBean实现了BeanPostProcessor,所以在每个bean 的初始化之前和之后,分别会调用AnnotationBean的postProcessBeforeInitialization和 postProcessAfterInitialization方法。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//判断此bean是否在包扫描路径下。如果不在路径下,则不做任何处理 if (! isMatchPackage(bean)) { return bean; }//分析bean所有的set方法,是否有Reference注解。如果有,则注入。 Method[] methods = bean.getClass().getMethods(); for (Method method : methods) { String name = method.getName(); if (name.length() > 3 && name.startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers()) && ! Modifier.isStatic(method.getModifiers())) { try { Reference reference = method.getAnnotation(Reference.class); if (reference != null) { Object value = refer(reference, method.getParameterTypes()[0]); if (value != null) { method.invoke(bean, new Object[] { }); } } } catch (Throwable e) { } } }//分析bean所有的成员,如果有Reference注解,则注入。 Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { try { if (! field.isAccessible()) { field.setAccessible(true); } Reference reference = field.getAnnotation(Reference.class); if (reference != null) { Object value = refer(reference, field.getType()); if (value != null) { field.set(bean, value); } } } catch (Throwable e) { } } return bean;}
通过以上的逻辑可以知道,Dubbo支持成员和set方法的注解。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {//判断所在包是否被扫描 if (! isMatchPackage(bean)) { return bean; }//如果Bean有Service注解,则实例化ServiceBean,承载此注解及注解描述的Bean。Service service = bean.getClass().getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if (bean.getClass().getInterfaces().length > 0) { serviceConfig.setInterface(bean.getClass().getInterfaces()[0]); } else { throw new IllegalStateException("Failed to export remote service class " + bean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); } } if (applicationContext != null) { serviceConfig.setApplicationContext(applicationContext); ................. if (service.protocol() != null && service.protocol().length > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (String protocolId : service.registry()) { if (protocolId != null && protocolId.length() > 0) { protocolConfigs.add((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException e) { } } serviceConfig.setRef(bean); serviceConfigs.add(serviceConfig);//export此bean。 serviceConfig.export(); } return bean;}
由源码可以看出,servicebean是通过AnnotationBean实现export调用的。
4. ServiceBean export
ServiceBean 可以通过xml配置,也可以通过注解配置.所以,export方法的调用点也是两处:serviceBean的afterPropertiesSet接口 函数和AnnotationBean的postProcessAfterInitialization.这里介绍注解方式,所以从 AnnotationBean的切入点入手.在AnnotationBean中,根据ServiceBean(spring内注册bean)的信息,创建 一个新的ServiceConfigBean(dubbo内bean),并填充 provider,application,monitor, module, provider, protocol,ref等属性. 之后调用ServiceConfigBean.export().
Export的核心功能在doExportUrls中实现。核心代码:
//配置为none不暴露 if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) { //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务) if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) { exportLocal(url); } //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务) if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){ if (registryURLs != null && registryURLs.size() > 0 && url.getParameter("register", true)) { for (URL registryURL : registryURLs) { url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic")); URL monitorUrl = loadMonitor(registryURL); if (monitorUrl != null) { url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString()); } Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class<T>) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString())); Exporter<?> exporter = protocol.export(invoker); exporters.add(exporter); } } else { Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class<T>) interfaceClass, url); Exporter<?> exporter = protocol.export(invoker); exporters.add(exporter); } } }
protocol.export(invoker)实现了service的注册中心注册。 Protocol基于dubboProtocol扩展,利用扩展点的方式实现切面。调用框 架:ProtocolFilterWrapper->ProtocolListenerWrapper ->RegistryProtocol。真正的注册方法在RegistryProtocol中实现。
扩展点的思想贯穿dubbo的整个设计,也是dubbo扩展各种功能的基础。之后会进行详细介绍。
http://my.oschina.net/u/347227/blog/367703
- dubbo service export过程
- dubbo 无法启动 injvm.InjvmProtocol export service
- dubbo暴露服务过程
- dubbo的通信过程
- Dubbo调用过程监控
- junit测试service,支持dubbo
- dubbo forbid service的解决办法
- sqoop export SQLSERVER 存储过程参数限制
- Dubbo源码分析(三):Dubbo之服务端(Service)
- Dubbo源码分析(三):Dubbo之服务端(Service)
- Dubbo源码分析(三):Dubbo之服务端(Service)
- Dubbo-----Dubbo不能同时使用@Service和@Transactional
- Dubbo系列(三)Dubbo之service实际调用注意事项
- export
- export
- export
- Export
- export
- Android Cache 解析
- Jest
- Caffe中把数据转换成灰度图
- Java字符串全角转半角
- 【学习笔记】图像RGB三个分量的理解与显示
- dubbo service export过程
- android studio可恶的so文件
- 工厂模式的简单实现和快速理解--------(java复习)
- Spring对注解(Annotation)处理源码分析1——扫描和读取Bean定义
- 利用webstrom的宏,保存文件自动格式化代码
- Qt的4个图像类QImage/QPixmap/QBitmap/QPicture
- Spring对注解(Annotation)处理源码分析2——解析和注入注解配置的资源
- leetcode-12 Integer to Roman
- 朴素模式匹配算法java实现