`
m635674608
  • 浏览: 5026705 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

dubbo service export过程

 
阅读更多

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提供与调用

    在服务提供者侧,服务通过`&lt;dubbo:service&gt;`标签暴露: ```xml &lt;dubbo:service interface="com.example.MyService" ref="myServiceImpl" /&gt; ``` 而在服务消费者侧,通过`&lt;dubbo:reference&gt;`标签引用服务: ```...

    dubbo源码解析2

    4. **Java RPC机制**:理解RPC(远程过程调用)的概念是学习Dubbo的关键之一。可以先从RMI、Hessian、Thrift等RPC框架入手,了解它们的工作原理及其与Dubbo之间的联系。 5. **Java其他内容**:除了以上提及的知识点...

    dubbo源码解析

    13. Refer&export过程分析:研究了Dubbo中服务的暴露(export)和引用(refer)的流程,包括调用顺序、生成Invoker的过程、Registry的使用等。 14. 集群和容错处理:描述了Dubbo中的集群机制,包括路由服务、负载...

    dubbo-demo.zip

    3. **服务暴露(Service Export)**:服务提供者启动后,通过Dubbo的API将服务暴露出去,注册到注册中心。 4. **服务引用(Service Reference)**:服务消费者通过Dubbo API引用服务,获取服务代理对象,进而调用...

    dubbo2.5.7 源码包

    源码中,`com.alibaba.dubbo.rpc.service.GenericService`是所有服务接口的基类,定义了服务的基本行为。 1.2 服务消费者(Consumer) 服务消费者是服务的使用者,通过注册中心获取服务提供者的地址并进行调用。`...

    Dubbo使用示例

    在Spring配置文件中,我们可以配置`dubbo:service`元素来暴露服务,或者使用`@Export`注解: ```xml &lt;dubbo:service interface="com.example.UserService" ref="userService" version="1.0.0"/&gt; ``` 或者 ```java...

    dubbo 的安装

    以上就是Dubbo的安装过程,需要注意的是,实际部署时可能需要根据具体环境调整配置,如注册中心类型(Zookeeper、Nacos等)、网络环境等。同时,Dubbo还提供了许多高级特性,如集群策略、过滤器、监控等,可以根据...

    dubbo2.0-源码阅读

    1. **Refer&export**:Dubbo中的服务引用和暴露过程。主要包括调用顺序、生成Invoker、暴露服务等步骤。 2. **Registry**:Dubbo的服务注册中心,用于服务的注册与发现。主要包括: - RegistryFactory和Registry:...

    dubbo+zookeeper入门实例

    - **服务暴露(Export)**:服务提供者通过`&lt;dubbo:service&gt;`标签暴露服务。 - **服务引用(Reference)**:服务消费者通过`&lt;dubbo:reference&gt;`标签引用服务。 5. **启动流程** - 启动Zookeeper服务器。 - 运行...

    dubbo-provider.zip

    9. **服务暴露(Export)**:服务提供者通过`dubbo:service`标签暴露服务,定义了服务的元数据。 深入理解Dubbo服务提供者,我们需要关注服务的生命周期管理、服务的负载均衡策略、服务的容错机制、服务的调用链...

    dubbo 分布式搭建源码

    【Dubbo 分布式搭建源码详解】 Dubbo 是阿里巴巴开源的一款高性能、轻量级的 Java RPC 框架,它提供了服务治理、负载均衡、容错机制等核心功能,广泛应用于微服务架构中。本资源是基于博客“Dubbo+zookeeper 最简单...

    dubbo源码解析2.01.pdf

    - **Java SPI**:Dubbo使用Java SPI(Service Provider Interface)机制来实现扩展点的自动发现和加载。 - **扩展点**:扩展点是指Dubbo中可以通过配置来动态替换实现的功能点,例如序列化方式、负载均衡策略等。 ...

    dubbo-2.8.4.jar

    dubbo微服务框架 Dubbo is a distributed, high performance RPC framework which empowers applications with service import/export capabilities.

    dubbo的服务发布与服务引用

    本文将深入源码,详细解析这两个关键过程,帮助你理解Dubbo是如何在服务提供者和服务消费者之间建立通信桥梁的。 一、服务发布 1. 配置服务:首先,服务提供者需要在配置文件(如Spring XML)中定义服务接口及其...

    dubbo——标签解析、服务暴露、服务引用、服务调用1

    Dubbo的配置通常通过Spring的XML文件进行,其中包含特定的Dubbo标签,如`&lt;dubbo:service&gt;`和`&lt;dubbo:reference&gt;`. 这些标签的解析由`DubboBeanDefinitionParser`实现,它是一个实现了Spring的`BeanDefinitionParser`...

    Dubbo+zookeeper调用java接口

    4. **暴露服务(Export Service)**:服务提供者通过Dubbo的API或XML配置暴露服务,这会将服务注册到Zookeeper。 5. **引用服务(Refer Service)**:服务消费者通过Dubbo的API或XML配置引用服务,从Zookeeper获取...

    dubbo_demo实例

    - **服务暴露(Service Export)**:服务提供者通过`&lt;dubbo:service&gt;`标签将服务暴露出去,包括接口名、实现类、版本号等信息。 - **服务引用(Service Reference)**:服务消费者通过`&lt;dubbo:reference&gt;`标签引用...

    dubbo demo 入门基础

    3. **服务暴露(Service Export)**:服务提供者通过Dubbo API将其服务暴露出去。 4. **服务引用(Service Reference)**:服务消费者通过Dubbo API引用服务提供者的服务。 5. **服务调用(Service Invocation)**:...

Global site tag (gtag.js) - Google Analytics